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 5 // Package proxy provides support for a variety of protocols to proxy network 6 // data. 7 package proxy // import "golang.org/x/net/proxy" 8 9 import ( 10 "errors" 11 "net" 12 "net/url" 13 "os" 14 ) 15 16 // A Dialer is a means to establish a connection. 17 type Dialer interface { 18 // Dial connects to the given address via the proxy. 19 Dial(network, addr string) (c net.Conn, err error) 20 } 21 22 // Auth contains authentication parameters that specific Dialers may require. 23 type Auth struct { 24 User, Password string 25 } 26 27 // FromEnvironment returns the dialer specified by the proxy related variables in 28 // the environment. 29 func FromEnvironment() Dialer { 30 allProxy := os.Getenv("all_proxy") 31 if len(allProxy) == 0 { 32 return Direct 33 } 34 35 proxyURL, err := url.Parse(allProxy) 36 if err != nil { 37 return Direct 38 } 39 proxy, err := FromURL(proxyURL, Direct) 40 if err != nil { 41 return Direct 42 } 43 44 noProxy := os.Getenv("no_proxy") 45 if len(noProxy) == 0 { 46 return proxy 47 } 48 49 perHost := NewPerHost(proxy, Direct) 50 perHost.AddFromString(noProxy) 51 return perHost 52 } 53 54 // proxySchemes is a map from URL schemes to a function that creates a Dialer 55 // from a URL with such a scheme. 56 var proxySchemes map[string]func(*url.URL, Dialer) (Dialer, error) 57 58 // RegisterDialerType takes a URL scheme and a function to generate Dialers from 59 // a URL with that scheme and a forwarding Dialer. Registered schemes are used 60 // by FromURL. 61 func RegisterDialerType(scheme string, f func(*url.URL, Dialer) (Dialer, error)) { 62 if proxySchemes == nil { 63 proxySchemes = make(map[string]func(*url.URL, Dialer) (Dialer, error)) 64 } 65 proxySchemes[scheme] = f 66 } 67 68 // FromURL returns a Dialer given a URL specification and an underlying 69 // Dialer for it to make network requests. 70 func FromURL(u *url.URL, forward Dialer) (Dialer, error) { 71 var auth *Auth 72 if u.User != nil { 73 auth = new(Auth) 74 auth.User = u.User.Username() 75 if p, ok := u.User.Password(); ok { 76 auth.Password = p 77 } 78 } 79 80 switch u.Scheme { 81 case "socks5": 82 return SOCKS5("tcp", u.Host, auth, forward) 83 } 84 85 // If the scheme doesn't match any of the built-in schemes, see if it 86 // was registered by another package. 87 if proxySchemes != nil { 88 if f, ok := proxySchemes[u.Scheme]; ok { 89 return f(u, forward) 90 } 91 } 92 93 return nil, errors.New("proxy: unknown scheme: " + u.Scheme) 94 } 95