http_test.go 9.0 KB

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