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