blob: 78a8b7bee97aa07b25c232314546b5b3a3b6731a [file] [log] [blame]
David K. Bainbridge215e0242017-09-05 23:18:24 -07001// 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.
7package proxy // import "golang.org/x/net/proxy"
8
9import (
10 "errors"
11 "net"
12 "net/url"
13 "os"
14)
15
16// A Dialer is a means to establish a connection.
17type 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.
23type Auth struct {
24 User, Password string
25}
26
27// FromEnvironment returns the dialer specified by the proxy related variables in
28// the environment.
29func 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.
56var 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.
61func 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.
70func 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}