mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-31 00:22:26 -05:00 
			
		
		
		
	
		
			
	
	
		
			150 lines
		
	
	
	
		
			3.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			150 lines
		
	
	
	
		
			3.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
|  | // 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 = "" | ||
|  | } |