proxy_test.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. // Copyright 2011 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package proxy
  5. import (
  6. "bytes"
  7. "context"
  8. "errors"
  9. "fmt"
  10. "net"
  11. "net/url"
  12. "os"
  13. "strings"
  14. "testing"
  15. "golang.org/x/net/internal/socks"
  16. "golang.org/x/net/internal/sockstest"
  17. )
  18. type proxyFromEnvTest struct {
  19. allProxyEnv string
  20. noProxyEnv string
  21. wantTypeOf Dialer
  22. }
  23. func (t proxyFromEnvTest) String() string {
  24. var buf bytes.Buffer
  25. space := func() {
  26. if buf.Len() > 0 {
  27. buf.WriteByte(' ')
  28. }
  29. }
  30. if t.allProxyEnv != "" {
  31. fmt.Fprintf(&buf, "all_proxy=%q", t.allProxyEnv)
  32. }
  33. if t.noProxyEnv != "" {
  34. space()
  35. fmt.Fprintf(&buf, "no_proxy=%q", t.noProxyEnv)
  36. }
  37. return strings.TrimSpace(buf.String())
  38. }
  39. func TestFromEnvironment(t *testing.T) {
  40. ResetProxyEnv()
  41. type dummyDialer struct {
  42. direct
  43. }
  44. RegisterDialerType("irc", func(_ *url.URL, _ Dialer) (Dialer, error) {
  45. return dummyDialer{}, nil
  46. })
  47. proxyFromEnvTests := []proxyFromEnvTest{
  48. {allProxyEnv: "127.0.0.1:8080", noProxyEnv: "localhost, 127.0.0.1", wantTypeOf: direct{}},
  49. {allProxyEnv: "ftp://example.com:8000", noProxyEnv: "localhost, 127.0.0.1", wantTypeOf: direct{}},
  50. {allProxyEnv: "socks5://example.com:8080", noProxyEnv: "localhost, 127.0.0.1", wantTypeOf: &PerHost{}},
  51. {allProxyEnv: "socks5h://example.com", wantTypeOf: &socks.Dialer{}},
  52. {allProxyEnv: "irc://example.com:8000", wantTypeOf: dummyDialer{}},
  53. {noProxyEnv: "localhost, 127.0.0.1", wantTypeOf: direct{}},
  54. {wantTypeOf: direct{}},
  55. }
  56. for _, tt := range proxyFromEnvTests {
  57. os.Setenv("ALL_PROXY", tt.allProxyEnv)
  58. os.Setenv("NO_PROXY", tt.noProxyEnv)
  59. ResetCachedEnvironment()
  60. d := FromEnvironment()
  61. if got, want := fmt.Sprintf("%T", d), fmt.Sprintf("%T", tt.wantTypeOf); got != want {
  62. t.Errorf("%v: got type = %T, want %T", tt, d, tt.wantTypeOf)
  63. }
  64. }
  65. }
  66. func TestFromURL(t *testing.T) {
  67. ss, err := sockstest.NewServer(sockstest.NoAuthRequired, sockstest.NoProxyRequired)
  68. if err != nil {
  69. t.Fatal(err)
  70. }
  71. defer ss.Close()
  72. url, err := url.Parse("socks5://user:password@" + ss.Addr().String())
  73. if err != nil {
  74. t.Fatal(err)
  75. }
  76. proxy, err := FromURL(url, nil)
  77. if err != nil {
  78. t.Fatal(err)
  79. }
  80. c, err := proxy.Dial("tcp", "fqdn.doesnotexist:5963")
  81. if err != nil {
  82. t.Fatal(err)
  83. }
  84. c.Close()
  85. }
  86. func TestSOCKS5(t *testing.T) {
  87. ss, err := sockstest.NewServer(sockstest.NoAuthRequired, sockstest.NoProxyRequired)
  88. if err != nil {
  89. t.Fatal(err)
  90. }
  91. defer ss.Close()
  92. proxy, err := SOCKS5("tcp", ss.Addr().String(), nil, nil)
  93. if err != nil {
  94. t.Fatal(err)
  95. }
  96. c, err := proxy.Dial("tcp", ss.TargetAddr().String())
  97. if err != nil {
  98. t.Fatal(err)
  99. }
  100. c.Close()
  101. }
  102. type funcFailDialer func(context.Context) error
  103. func (f funcFailDialer) Dial(net, addr string) (net.Conn, error) {
  104. panic("shouldn't see a call to Dial")
  105. }
  106. func (f funcFailDialer) DialContext(ctx context.Context, net, addr string) (net.Conn, error) {
  107. return nil, f(ctx)
  108. }
  109. // Check that FromEnvironmentUsing uses our dialer.
  110. func TestFromEnvironmentUsing(t *testing.T) {
  111. ResetProxyEnv()
  112. errFoo := errors.New("some error to check our dialer was used)")
  113. type key string
  114. ctx := context.WithValue(context.Background(), key("foo"), "bar")
  115. dialer := FromEnvironmentUsing(funcFailDialer(func(ctx context.Context) error {
  116. if got := ctx.Value(key("foo")); got != "bar" {
  117. t.Errorf("Resolver context = %T %v, want %q", got, got, "bar")
  118. }
  119. return errFoo
  120. }))
  121. _, err := dialer.(ContextDialer).DialContext(ctx, "tcp", "foo.tld:123")
  122. if err == nil {
  123. t.Fatalf("unexpected success")
  124. }
  125. if !strings.Contains(err.Error(), errFoo.Error()) {
  126. t.Errorf("got unexpected error %q; want substr %q", err, errFoo)
  127. }
  128. }
  129. func ResetProxyEnv() {
  130. for _, env := range []*envOnce{allProxyEnv, noProxyEnv} {
  131. for _, v := range env.names {
  132. os.Setenv(v, "")
  133. }
  134. }
  135. ResetCachedEnvironment()
  136. }
  137. func ResetCachedEnvironment() {
  138. allProxyEnv.reset()
  139. noProxyEnv.reset()
  140. }