|
- // Copyright 2011 The Go Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
-
- // Package proxy provides support for a variety of protocols to proxy network
- // data.
- package proxy // import "golang.org/x/net/proxy"
-
- import (
- "errors"
- "net"
- "net/url"
- "os"
- "sync"
- )
-
- // A Dialer is a means to establish a connection.
- // Custom dialers should also implement ContextDialer.
- type Dialer interface {
- // Dial connects to the given address via the proxy.
- Dial(network, addr string) (c net.Conn, err error)
- }
-
- // Auth contains authentication parameters that specific Dialers may require.
- type Auth struct {
- User, Password string
- }
-
- // FromEnvironment returns the dialer specified by the proxy-related
- // variables in the environment and makes underlying connections
- // directly.
- func FromEnvironment() Dialer {
- return FromEnvironmentUsing(Direct)
- }
-
- // FromEnvironmentUsing returns the dialer specify by the proxy-related
- // variables in the environment and makes underlying connections
- // using the provided forwarding Dialer (for instance, a *net.Dialer
- // with desired configuration).
- func FromEnvironmentUsing(forward Dialer) Dialer {
- allProxy := allProxyEnv.Get()
- if len(allProxy) == 0 {
- return forward
- }
-
- proxyURL, err := url.Parse(allProxy)
- if err != nil {
- return forward
- }
- proxy, err := FromURL(proxyURL, forward)
- if err != nil {
- return forward
- }
-
- noProxy := noProxyEnv.Get()
- if len(noProxy) == 0 {
- return proxy
- }
-
- perHost := NewPerHost(proxy, forward)
- perHost.AddFromString(noProxy)
- return perHost
- }
-
- // proxySchemes is a map from URL schemes to a function that creates a Dialer
- // from a URL with such a scheme.
- var proxySchemes map[string]func(*url.URL, Dialer) (Dialer, error)
-
- // RegisterDialerType takes a URL scheme and a function to generate Dialers from
- // a URL with that scheme and a forwarding Dialer. Registered schemes are used
- // by FromURL.
- func RegisterDialerType(scheme string, f func(*url.URL, Dialer) (Dialer, error)) {
- if proxySchemes == nil {
- proxySchemes = make(map[string]func(*url.URL, Dialer) (Dialer, error))
- }
- proxySchemes[scheme] = f
- }
-
- // FromURL returns a Dialer given a URL specification and an underlying
- // Dialer for it to make network requests.
- func FromURL(u *url.URL, forward Dialer) (Dialer, error) {
- var auth *Auth
- if u.User != nil {
- auth = new(Auth)
- auth.User = u.User.Username()
- if p, ok := u.User.Password(); ok {
- auth.Password = p
- }
- }
-
- switch u.Scheme {
- case "socks5", "socks5h":
- addr := u.Hostname()
- port := u.Port()
- if port == "" {
- port = "1080"
- }
- return SOCKS5("tcp", net.JoinHostPort(addr, port), auth, forward)
- }
-
- // If the scheme doesn't match any of the built-in schemes, see if it
- // was registered by another package.
- if proxySchemes != nil {
- if f, ok := proxySchemes[u.Scheme]; ok {
- return f(u, forward)
- }
- }
-
- return nil, errors.New("proxy: unknown scheme: " + u.Scheme)
- }
-
- var (
- allProxyEnv = &envOnce{
- names: []string{"ALL_PROXY", "all_proxy"},
- }
- noProxyEnv = &envOnce{
- names: []string{"NO_PROXY", "no_proxy"},
- }
- )
-
- // envOnce looks up an environment variable (optionally by multiple
- // names) once. It mitigates expensive lookups on some platforms
- // (e.g. Windows).
- // (Borrowed from net/http/transport.go)
- type envOnce struct {
- names []string
- once sync.Once
- val string
- }
-
- func (e *envOnce) Get() string {
- e.once.Do(e.init)
- return e.val
- }
-
- func (e *envOnce) init() {
- for _, n := range e.names {
- e.val = os.Getenv(n)
- if e.val != "" {
- return
- }
- }
- }
-
- // reset is used by tests
- func (e *envOnce) reset() {
- e.once = sync.Once{}
- e.val = ""
- }
|