mirror of
https://github.com/valyala/fasthttp.git
synced 2026-06-25 17:45:28 +03:00
Added proxy from env support (#885)
* added proxy from env support * fixed package name * fixed err wrapping * evoid 2 err wrapping in the same format
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
package fasthttpproxy
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/http/httpproxy"
|
||||
|
||||
"github.com/valyala/fasthttp"
|
||||
)
|
||||
|
||||
// FasthttpProxyHTTPDialer returns a fasthttp.DialFunc that dials using
|
||||
// the the env(HTTP_PROXY, HTTPS_PROXY and NO_PROXY) configured HTTP proxy.
|
||||
//
|
||||
// Example usage:
|
||||
// c := &fasthttp.Client{
|
||||
// Dial: FasthttpProxyHTTPDialer(),
|
||||
// }
|
||||
func FasthttpProxyHTTPDialer() fasthttp.DialFunc {
|
||||
return FasthttpProxyHTTPDialerTimeout(0)
|
||||
}
|
||||
|
||||
// FasthttpProxyHTTPDialer returns a fasthttp.DialFunc that dials using
|
||||
// the env(HTTP_PROXY, HTTPS_PROXY and NO_PROXY) configured HTTP proxy using the given timeout.
|
||||
//
|
||||
// Example usage:
|
||||
// c := &fasthttp.Client{
|
||||
// Dial: FasthttpProxyHTTPDialerTimeout(time.Second * 2),
|
||||
// }
|
||||
func FasthttpProxyHTTPDialerTimeout(timeout time.Duration) fasthttp.DialFunc {
|
||||
proxier := httpproxy.FromEnvironment().ProxyFunc()
|
||||
|
||||
// map on proxy URL and its encoded auth barrier
|
||||
authBarriers := map[*url.URL]string{}
|
||||
authBarriersLock := sync.RWMutex{}
|
||||
|
||||
return func(addr string) (net.Conn, error) {
|
||||
|
||||
proxyURL, err := proxier(&url.URL{Host: addr})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if proxyURL == nil {
|
||||
if timeout == 0 {
|
||||
return fasthttp.Dial(addr)
|
||||
}
|
||||
return fasthttp.DialTimeout(addr, timeout)
|
||||
}
|
||||
|
||||
var conn net.Conn
|
||||
if timeout == 0 {
|
||||
conn, err = fasthttp.Dial(proxyURL.String())
|
||||
} else {
|
||||
conn, err = fasthttp.DialTimeout(proxyURL.String(), timeout)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := "CONNECT " + addr + " HTTP/1.1\r\n"
|
||||
if proxyURL.User != nil {
|
||||
authBarriersLock.RLock()
|
||||
barrier, ok := authBarriers[proxyURL]
|
||||
authBarriersLock.RUnlock()
|
||||
|
||||
if !ok {
|
||||
barrier = base64.StdEncoding.EncodeToString([]byte(proxyURL.User.String()))
|
||||
authBarriersLock.Lock()
|
||||
authBarriers[proxyURL] = barrier
|
||||
authBarriersLock.Unlock()
|
||||
}
|
||||
|
||||
req += "Proxy-Authorization: Basic " + barrier + "\r\n"
|
||||
}
|
||||
req += "\r\n"
|
||||
|
||||
if _, err := conn.Write([]byte(req)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res := fasthttp.AcquireResponse()
|
||||
defer fasthttp.ReleaseResponse(res)
|
||||
|
||||
res.SkipBody = true
|
||||
|
||||
if err := res.Read(bufio.NewReader(conn)); err != nil {
|
||||
if connErr := conn.Close(); connErr != nil {
|
||||
return nil, fmt.Errorf("conn close err %v followed by read conn err %w", connErr, err)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
if res.Header.StatusCode() != 200 {
|
||||
if connErr := conn.Close(); connErr != nil {
|
||||
return nil, fmt.Errorf(
|
||||
"conn close err %v followed by connect to proxy: code: %d body %s",
|
||||
connErr, res.StatusCode(), string(res.Body()))
|
||||
}
|
||||
return nil, fmt.Errorf("could not connect to proxy: code: %d body %s", res.StatusCode(), string(res.Body()))
|
||||
}
|
||||
return conn, nil
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ require (
|
||||
github.com/klauspost/compress v1.10.7
|
||||
github.com/valyala/bytebufferpool v1.0.0
|
||||
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2
|
||||
golang.org/x/net v0.0.0-20200602114024-627f9648deb9
|
||||
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
|
||||
golang.org/x/net v0.0.0-20201016165138-7b1cca2348c0
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f
|
||||
)
|
||||
|
||||
@@ -8,10 +8,17 @@ github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a h1:0R4NLDRDZX6Jc
|
||||
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/net v0.0.0-20200602114024-627f9648deb9 h1:pNX+40auqi2JqRfOP1akLGtYcn15TUbkhwuCO3foqqM=
|
||||
golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20201016165138-7b1cca2348c0 h1:5kGOVHlq0euqwzgTC9Vu15p6fV1Wi0ArVi8da2urnVg=
|
||||
golang.org/x/net v0.0.0-20201016165138-7b1cca2348c0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980 h1:OjiUf46hAmXblsZdnoSXsEUSKU8r1UEzcL5RVZ4gO9Y=
|
||||
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
|
||||
Reference in New Issue
Block a user