source: code/trunk/vendor/github.com/valyala/fasthttp/fasthttpproxy/proxy_env.go@ 145

Last change on this file since 145 was 145, checked in by Izuru Yakumo, 22 months ago

Updated the Makefile and vendored depedencies

Signed-off-by: Izuru Yakumo <yakumo.izuru@…>

File size: 3.0 KB
Line 
1package fasthttpproxy
2
3import (
4 "bufio"
5 "encoding/base64"
6 "fmt"
7 "net"
8 "net/url"
9 "sync/atomic"
10 "time"
11
12 "golang.org/x/net/http/httpproxy"
13
14 "github.com/valyala/fasthttp"
15)
16
17const (
18 httpsScheme = "https"
19 httpScheme = "http"
20 tlsPort = "443"
21)
22
23// FasthttpProxyHTTPDialer returns a fasthttp.DialFunc that dials using
24// the the env(HTTP_PROXY, HTTPS_PROXY and NO_PROXY) configured HTTP proxy.
25//
26// Example usage:
27// c := &fasthttp.Client{
28// Dial: FasthttpProxyHTTPDialer(),
29// }
30func FasthttpProxyHTTPDialer() fasthttp.DialFunc {
31 return FasthttpProxyHTTPDialerTimeout(0)
32}
33
34// FasthttpProxyHTTPDialer returns a fasthttp.DialFunc that dials using
35// the env(HTTP_PROXY, HTTPS_PROXY and NO_PROXY) configured HTTP proxy using the given timeout.
36//
37// Example usage:
38// c := &fasthttp.Client{
39// Dial: FasthttpProxyHTTPDialerTimeout(time.Second * 2),
40// }
41func FasthttpProxyHTTPDialerTimeout(timeout time.Duration) fasthttp.DialFunc {
42 proxier := httpproxy.FromEnvironment().ProxyFunc()
43
44 // encoded auth barrier for http and https proxy.
45 authHTTPStorage := &atomic.Value{}
46 authHTTPSStorage := &atomic.Value{}
47
48 return func(addr string) (net.Conn, error) {
49
50 port, _, err := net.SplitHostPort(addr)
51 if err != nil {
52 return nil, fmt.Errorf("unexpected addr format: %w", err)
53 }
54
55 reqURL := &url.URL{Host: addr, Scheme: httpScheme}
56 if port == tlsPort {
57 reqURL.Scheme = httpsScheme
58 }
59 proxyURL, err := proxier(reqURL)
60 if err != nil {
61 return nil, err
62 }
63
64 if proxyURL == nil {
65 if timeout == 0 {
66 return fasthttp.Dial(addr)
67 }
68 return fasthttp.DialTimeout(addr, timeout)
69 }
70
71 var conn net.Conn
72 if timeout == 0 {
73 conn, err = fasthttp.Dial(proxyURL.Host)
74 } else {
75 conn, err = fasthttp.DialTimeout(proxyURL.Host, timeout)
76 }
77 if err != nil {
78 return nil, err
79 }
80
81 req := "CONNECT " + addr + " HTTP/1.1\r\n"
82
83 if proxyURL.User != nil {
84 authBarrierStorage := authHTTPStorage
85 if port == tlsPort {
86 authBarrierStorage = authHTTPSStorage
87 }
88
89 auth := authBarrierStorage.Load()
90 if auth == nil {
91 authBarrier := base64.StdEncoding.EncodeToString([]byte(proxyURL.User.String()))
92 auth := &authBarrier
93 authBarrierStorage.Store(auth)
94 }
95
96 req += "Proxy-Authorization: Basic " + *auth.(*string) + "\r\n"
97 }
98 req += "\r\n"
99
100 if _, err := conn.Write([]byte(req)); err != nil {
101 return nil, err
102 }
103
104 res := fasthttp.AcquireResponse()
105 defer fasthttp.ReleaseResponse(res)
106
107 res.SkipBody = true
108
109 if err := res.Read(bufio.NewReader(conn)); err != nil {
110 if connErr := conn.Close(); connErr != nil {
111 return nil, fmt.Errorf("conn close err %v precede by read conn err %w", connErr, err)
112 }
113 return nil, err
114 }
115 if res.Header.StatusCode() != 200 {
116 if connErr := conn.Close(); connErr != nil {
117 return nil, fmt.Errorf(
118 "conn close err %w precede by connect to proxy: code: %d body %s",
119 connErr, res.StatusCode(), string(res.Body()))
120 }
121 return nil, fmt.Errorf("could not connect to proxy: code: %d body %s", res.StatusCode(), string(res.Body()))
122 }
123 return conn, nil
124 }
125}
Note: See TracBrowser for help on using the repository browser.