No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 

140 líneas
3.2 KiB

  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 provides support for a variety of protocols to proxy network
  5. // data.
  6. package proxy // import "golang.org/x/net/proxy"
  7. import (
  8. "errors"
  9. "net"
  10. "net/url"
  11. "os"
  12. "sync"
  13. )
  14. // A Dialer is a means to establish a connection.
  15. type Dialer interface {
  16. // Dial connects to the given address via the proxy.
  17. Dial(network, addr string) (c net.Conn, err error)
  18. }
  19. // Auth contains authentication parameters that specific Dialers may require.
  20. type Auth struct {
  21. User, Password string
  22. }
  23. // FromEnvironment returns the dialer specified by the proxy related variables in
  24. // the environment.
  25. func FromEnvironment() Dialer {
  26. allProxy := allProxyEnv.Get()
  27. if len(allProxy) == 0 {
  28. return Direct
  29. }
  30. proxyURL, err := url.Parse(allProxy)
  31. if err != nil {
  32. return Direct
  33. }
  34. proxy, err := FromURL(proxyURL, Direct)
  35. if err != nil {
  36. return Direct
  37. }
  38. noProxy := noProxyEnv.Get()
  39. if len(noProxy) == 0 {
  40. return proxy
  41. }
  42. perHost := NewPerHost(proxy, Direct)
  43. perHost.AddFromString(noProxy)
  44. return perHost
  45. }
  46. // proxySchemes is a map from URL schemes to a function that creates a Dialer
  47. // from a URL with such a scheme.
  48. var proxySchemes map[string]func(*url.URL, Dialer) (Dialer, error)
  49. // RegisterDialerType takes a URL scheme and a function to generate Dialers from
  50. // a URL with that scheme and a forwarding Dialer. Registered schemes are used
  51. // by FromURL.
  52. func RegisterDialerType(scheme string, f func(*url.URL, Dialer) (Dialer, error)) {
  53. if proxySchemes == nil {
  54. proxySchemes = make(map[string]func(*url.URL, Dialer) (Dialer, error))
  55. }
  56. proxySchemes[scheme] = f
  57. }
  58. // FromURL returns a Dialer given a URL specification and an underlying
  59. // Dialer for it to make network requests.
  60. func FromURL(u *url.URL, forward Dialer) (Dialer, error) {
  61. var auth *Auth
  62. if u.User != nil {
  63. auth = new(Auth)
  64. auth.User = u.User.Username()
  65. if p, ok := u.User.Password(); ok {
  66. auth.Password = p
  67. }
  68. }
  69. switch u.Scheme {
  70. case "socks5", "socks5h":
  71. addr := u.Hostname()
  72. port := u.Port()
  73. if port == "" {
  74. port = "1080"
  75. }
  76. return SOCKS5("tcp", net.JoinHostPort(addr, port), auth, forward)
  77. }
  78. // If the scheme doesn't match any of the built-in schemes, see if it
  79. // was registered by another package.
  80. if proxySchemes != nil {
  81. if f, ok := proxySchemes[u.Scheme]; ok {
  82. return f(u, forward)
  83. }
  84. }
  85. return nil, errors.New("proxy: unknown scheme: " + u.Scheme)
  86. }
  87. var (
  88. allProxyEnv = &envOnce{
  89. names: []string{"ALL_PROXY", "all_proxy"},
  90. }
  91. noProxyEnv = &envOnce{
  92. names: []string{"NO_PROXY", "no_proxy"},
  93. }
  94. )
  95. // envOnce looks up an environment variable (optionally by multiple
  96. // names) once. It mitigates expensive lookups on some platforms
  97. // (e.g. Windows).
  98. // (Borrowed from net/http/transport.go)
  99. type envOnce struct {
  100. names []string
  101. once sync.Once
  102. val string
  103. }
  104. func (e *envOnce) Get() string {
  105. e.once.Do(e.init)
  106. return e.val
  107. }
  108. func (e *envOnce) init() {
  109. for _, n := range e.names {
  110. e.val = os.Getenv(n)
  111. if e.val != "" {
  112. return
  113. }
  114. }
  115. }
  116. // reset is used by tests
  117. func (e *envOnce) reset() {
  118. e.once = sync.Once{}
  119. e.val = ""
  120. }