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