1
0

netproxy_test.go 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. package netproxy
  2. import (
  3. "net/http"
  4. "net/http/httptest"
  5. "reflect"
  6. "testing"
  7. "time"
  8. )
  9. func TestNewHTTPClient(t *testing.T) {
  10. tests := []struct {
  11. name string
  12. proxyURL string
  13. wantErr bool
  14. wantProxy bool
  15. wantDial bool
  16. }{
  17. {name: "empty returns direct client", proxyURL: ""},
  18. {name: "socks5 sets custom dialer", proxyURL: "socks5://127.0.0.1:1080", wantDial: true},
  19. {name: "socks5 with auth", proxyURL: "socks5://user:[email protected]:1080", wantDial: true},
  20. {name: "http sets transport proxy", proxyURL: "http://127.0.0.1:8080", wantProxy: true},
  21. {name: "https sets transport proxy", proxyURL: "https://127.0.0.1:8080", wantProxy: true},
  22. {name: "unsupported scheme errors", proxyURL: "ftp://127.0.0.1:21", wantErr: true},
  23. }
  24. // baseTransport clones http.DefaultTransport, whose Proxy and DialContext are already
  25. // non-nil — so "!= nil" can't prove our proxy/dialer was applied. Check the real values.
  26. defaultDialPtr := reflect.ValueOf(http.DefaultTransport.(*http.Transport).DialContext).Pointer()
  27. for _, tc := range tests {
  28. t.Run(tc.name, func(t *testing.T) {
  29. client, err := NewHTTPClient(tc.proxyURL, 5*time.Second)
  30. if tc.wantErr {
  31. if err == nil {
  32. t.Fatalf("expected error for %q, got nil", tc.proxyURL)
  33. }
  34. return
  35. }
  36. if err != nil {
  37. t.Fatalf("unexpected error for %q: %v", tc.proxyURL, err)
  38. }
  39. if client.Timeout != 5*time.Second {
  40. t.Errorf("timeout = %v, want 5s", client.Timeout)
  41. }
  42. // Empty proxyURL → a plain direct client with no custom transport.
  43. if tc.proxyURL == "" {
  44. if client.Transport != nil {
  45. t.Errorf("empty proxy must yield a direct client (nil Transport), got %T", client.Transport)
  46. }
  47. return
  48. }
  49. transport, ok := client.Transport.(*http.Transport)
  50. if !ok {
  51. t.Fatalf("transport is %T, want *http.Transport", client.Transport)
  52. }
  53. if tc.wantProxy {
  54. // Prove the CONFIGURED proxy is applied: transport.Proxy(req) must
  55. // return our URL, not the cloned default's ProxyFromEnvironment.
  56. req := httptest.NewRequest(http.MethodGet, "https://example.com", nil)
  57. u, perr := transport.Proxy(req)
  58. if perr != nil {
  59. t.Fatalf("transport.Proxy returned error: %v", perr)
  60. }
  61. if u == nil || u.String() != tc.proxyURL {
  62. t.Errorf("transport.Proxy(req) = %v, want %q (configured proxy not applied)", u, tc.proxyURL)
  63. }
  64. }
  65. if tc.wantDial {
  66. if transport.DialContext == nil {
  67. t.Fatal("DialContext is nil")
  68. }
  69. // Must be the socks5 dialer, not the cloned default DialContext.
  70. if reflect.ValueOf(transport.DialContext).Pointer() == defaultDialPtr {
  71. t.Error("DialContext is still the default; socks5 dialer was not applied")
  72. }
  73. }
  74. })
  75. }
  76. }