Home | History | Annotate | Download | only in proxy
      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