github.com/imannamdari/v2ray-core/v5@v5.0.5/testing/scenarios/http_test.go (about) 1 package scenarios 2 3 import ( 4 "bytes" 5 "context" 6 "crypto/rand" 7 "io" 8 "net/http" 9 "net/url" 10 "testing" 11 "time" 12 13 "github.com/google/go-cmp/cmp" 14 15 core "github.com/imannamdari/v2ray-core/v5" 16 "github.com/imannamdari/v2ray-core/v5/app/proxyman" 17 "github.com/imannamdari/v2ray-core/v5/common" 18 "github.com/imannamdari/v2ray-core/v5/common/buf" 19 "github.com/imannamdari/v2ray-core/v5/common/net" 20 "github.com/imannamdari/v2ray-core/v5/common/serial" 21 "github.com/imannamdari/v2ray-core/v5/proxy/freedom" 22 v2http "github.com/imannamdari/v2ray-core/v5/proxy/http" 23 v2httptest "github.com/imannamdari/v2ray-core/v5/testing/servers/http" 24 "github.com/imannamdari/v2ray-core/v5/testing/servers/tcp" 25 ) 26 27 func TestHttpConformance(t *testing.T) { 28 httpServerPort := tcp.PickPort() 29 httpServer := &v2httptest.Server{ 30 Port: httpServerPort, 31 PathHandler: make(map[string]http.HandlerFunc), 32 } 33 _, err := httpServer.Start() 34 common.Must(err) 35 defer httpServer.Close() 36 37 serverPort := tcp.PickPort() 38 serverConfig := &core.Config{ 39 Inbound: []*core.InboundHandlerConfig{ 40 { 41 ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ 42 PortRange: net.SinglePortRange(serverPort), 43 Listen: net.NewIPOrDomain(net.LocalHostIP), 44 }), 45 ProxySettings: serial.ToTypedMessage(&v2http.ServerConfig{}), 46 }, 47 }, 48 Outbound: []*core.OutboundHandlerConfig{ 49 { 50 ProxySettings: serial.ToTypedMessage(&freedom.Config{}), 51 }, 52 }, 53 } 54 55 servers, err := InitializeServerConfigs(serverConfig) 56 common.Must(err) 57 defer CloseAllServers(servers) 58 59 { 60 transport := &http.Transport{ 61 Proxy: func(req *http.Request) (*url.URL, error) { 62 return url.Parse("http://127.0.0.1:" + serverPort.String()) 63 }, 64 } 65 66 client := &http.Client{ 67 Transport: transport, 68 } 69 70 resp, err := client.Get("http://127.0.0.1:" + httpServerPort.String()) 71 common.Must(err) 72 defer resp.Body.Close() 73 if resp.StatusCode != 200 { 74 t.Fatal("status: ", resp.StatusCode) 75 } 76 77 content, err := io.ReadAll(resp.Body) 78 common.Must(err) 79 if string(content) != "Home" { 80 t.Fatal("body: ", string(content)) 81 } 82 } 83 } 84 85 func TestHttpError(t *testing.T) { 86 tcpServer := tcp.Server{ 87 MsgProcessor: func(msg []byte) []byte { 88 return []byte{} 89 }, 90 } 91 dest, err := tcpServer.Start() 92 common.Must(err) 93 defer tcpServer.Close() 94 95 time.AfterFunc(time.Second*2, func() { 96 tcpServer.ShouldClose = true 97 }) 98 99 serverPort := tcp.PickPort() 100 serverConfig := &core.Config{ 101 Inbound: []*core.InboundHandlerConfig{ 102 { 103 ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ 104 PortRange: net.SinglePortRange(serverPort), 105 Listen: net.NewIPOrDomain(net.LocalHostIP), 106 }), 107 ProxySettings: serial.ToTypedMessage(&v2http.ServerConfig{}), 108 }, 109 }, 110 Outbound: []*core.OutboundHandlerConfig{ 111 { 112 ProxySettings: serial.ToTypedMessage(&freedom.Config{}), 113 }, 114 }, 115 } 116 117 servers, err := InitializeServerConfigs(serverConfig) 118 common.Must(err) 119 defer CloseAllServers(servers) 120 121 { 122 transport := &http.Transport{ 123 Proxy: func(req *http.Request) (*url.URL, error) { 124 return url.Parse("http://127.0.0.1:" + serverPort.String()) 125 }, 126 } 127 128 client := &http.Client{ 129 Transport: transport, 130 } 131 132 resp, err := client.Get("http://127.0.0.1:" + dest.Port.String()) 133 common.Must(err) 134 defer resp.Body.Close() 135 if resp.StatusCode != 503 { 136 t.Error("status: ", resp.StatusCode) 137 } 138 } 139 } 140 141 func TestHTTPConnectMethod(t *testing.T) { 142 tcpServer := tcp.Server{ 143 MsgProcessor: xor, 144 } 145 dest, err := tcpServer.Start() 146 common.Must(err) 147 defer tcpServer.Close() 148 149 serverPort := tcp.PickPort() 150 serverConfig := &core.Config{ 151 Inbound: []*core.InboundHandlerConfig{ 152 { 153 ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ 154 PortRange: net.SinglePortRange(serverPort), 155 Listen: net.NewIPOrDomain(net.LocalHostIP), 156 }), 157 ProxySettings: serial.ToTypedMessage(&v2http.ServerConfig{}), 158 }, 159 }, 160 Outbound: []*core.OutboundHandlerConfig{ 161 { 162 ProxySettings: serial.ToTypedMessage(&freedom.Config{}), 163 }, 164 }, 165 } 166 167 servers, err := InitializeServerConfigs(serverConfig) 168 common.Must(err) 169 defer CloseAllServers(servers) 170 171 { 172 transport := &http.Transport{ 173 Proxy: func(req *http.Request) (*url.URL, error) { 174 return url.Parse("http://127.0.0.1:" + serverPort.String()) 175 }, 176 } 177 178 client := &http.Client{ 179 Transport: transport, 180 } 181 182 payload := make([]byte, 1024*64) 183 common.Must2(rand.Read(payload)) 184 185 ctx := context.Background() 186 req, err := http.NewRequestWithContext(ctx, "Connect", "http://"+dest.NetAddr()+"/", bytes.NewReader(payload)) 187 req.Header.Set("X-a", "b") 188 req.Header.Set("X-b", "d") 189 common.Must(err) 190 191 resp, err := client.Do(req) 192 common.Must(err) 193 defer resp.Body.Close() 194 if resp.StatusCode != 200 { 195 t.Fatal("status: ", resp.StatusCode) 196 } 197 198 content := make([]byte, len(payload)) 199 common.Must2(io.ReadFull(resp.Body, content)) 200 if r := cmp.Diff(content, xor(payload)); r != "" { 201 t.Fatal(r) 202 } 203 } 204 } 205 206 func TestHttpPost(t *testing.T) { 207 httpServerPort := tcp.PickPort() 208 httpServer := &v2httptest.Server{ 209 Port: httpServerPort, 210 PathHandler: map[string]http.HandlerFunc{ 211 "/testpost": func(w http.ResponseWriter, r *http.Request) { 212 payload, err := buf.ReadAllToBytes(r.Body) 213 r.Body.Close() 214 215 if err != nil { 216 w.WriteHeader(500) 217 w.Write([]byte("Unable to read all payload")) 218 return 219 } 220 payload = xor(payload) 221 w.Write(payload) 222 }, 223 }, 224 } 225 226 _, err := httpServer.Start() 227 common.Must(err) 228 defer httpServer.Close() 229 230 serverPort := tcp.PickPort() 231 serverConfig := &core.Config{ 232 Inbound: []*core.InboundHandlerConfig{ 233 { 234 ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ 235 PortRange: net.SinglePortRange(serverPort), 236 Listen: net.NewIPOrDomain(net.LocalHostIP), 237 }), 238 ProxySettings: serial.ToTypedMessage(&v2http.ServerConfig{}), 239 }, 240 }, 241 Outbound: []*core.OutboundHandlerConfig{ 242 { 243 ProxySettings: serial.ToTypedMessage(&freedom.Config{}), 244 }, 245 }, 246 } 247 248 servers, err := InitializeServerConfigs(serverConfig) 249 common.Must(err) 250 defer CloseAllServers(servers) 251 252 { 253 transport := &http.Transport{ 254 Proxy: func(req *http.Request) (*url.URL, error) { 255 return url.Parse("http://127.0.0.1:" + serverPort.String()) 256 }, 257 } 258 259 client := &http.Client{ 260 Transport: transport, 261 } 262 263 payload := make([]byte, 1024*64) 264 common.Must2(rand.Read(payload)) 265 266 resp, err := client.Post("http://127.0.0.1:"+httpServerPort.String()+"/testpost", "application/x-www-form-urlencoded", bytes.NewReader(payload)) 267 common.Must(err) 268 defer resp.Body.Close() 269 if resp.StatusCode != 200 { 270 t.Fatal("status: ", resp.StatusCode) 271 } 272 273 content, err := io.ReadAll(resp.Body) 274 common.Must(err) 275 if r := cmp.Diff(content, xor(payload)); r != "" { 276 t.Fatal(r) 277 } 278 } 279 } 280 281 func setProxyBasicAuth(req *http.Request, user, pass string) { 282 req.SetBasicAuth(user, pass) 283 req.Header.Set("Proxy-Authorization", req.Header.Get("Authorization")) 284 req.Header.Del("Authorization") 285 } 286 287 func TestHttpBasicAuth(t *testing.T) { 288 httpServerPort := tcp.PickPort() 289 httpServer := &v2httptest.Server{ 290 Port: httpServerPort, 291 PathHandler: make(map[string]http.HandlerFunc), 292 } 293 _, err := httpServer.Start() 294 common.Must(err) 295 defer httpServer.Close() 296 297 serverPort := tcp.PickPort() 298 serverConfig := &core.Config{ 299 Inbound: []*core.InboundHandlerConfig{ 300 { 301 ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ 302 PortRange: net.SinglePortRange(serverPort), 303 Listen: net.NewIPOrDomain(net.LocalHostIP), 304 }), 305 ProxySettings: serial.ToTypedMessage(&v2http.ServerConfig{ 306 Accounts: map[string]string{ 307 "a": "b", 308 }, 309 }), 310 }, 311 }, 312 Outbound: []*core.OutboundHandlerConfig{ 313 { 314 ProxySettings: serial.ToTypedMessage(&freedom.Config{}), 315 }, 316 }, 317 } 318 319 servers, err := InitializeServerConfigs(serverConfig) 320 common.Must(err) 321 defer CloseAllServers(servers) 322 323 { 324 transport := &http.Transport{ 325 Proxy: func(req *http.Request) (*url.URL, error) { 326 return url.Parse("http://127.0.0.1:" + serverPort.String()) 327 }, 328 } 329 330 client := &http.Client{ 331 Transport: transport, 332 } 333 334 { 335 resp, err := client.Get("http://127.0.0.1:" + httpServerPort.String()) 336 common.Must(err) 337 defer resp.Body.Close() 338 if resp.StatusCode != 407 { 339 t.Fatal("status: ", resp.StatusCode) 340 } 341 } 342 343 { 344 ctx := context.Background() 345 req, err := http.NewRequestWithContext(ctx, "GET", "http://127.0.0.1:"+httpServerPort.String(), nil) 346 common.Must(err) 347 348 setProxyBasicAuth(req, "a", "c") 349 resp, err := client.Do(req) 350 common.Must(err) 351 defer resp.Body.Close() 352 if resp.StatusCode != 407 { 353 t.Fatal("status: ", resp.StatusCode) 354 } 355 } 356 357 { 358 ctx := context.Background() 359 req, err := http.NewRequestWithContext(ctx, "GET", "http://127.0.0.1:"+httpServerPort.String(), nil) 360 common.Must(err) 361 362 setProxyBasicAuth(req, "a", "b") 363 resp, err := client.Do(req) 364 common.Must(err) 365 defer resp.Body.Close() 366 if resp.StatusCode != 200 { 367 t.Fatal("status: ", resp.StatusCode) 368 } 369 370 content, err := io.ReadAll(resp.Body) 371 common.Must(err) 372 if string(content) != "Home" { 373 t.Fatal("body: ", string(content)) 374 } 375 } 376 } 377 }