mirror of https://github.com/golang/go.git
net/http: add Transport.ProxyConnectHeader to control headers to proxies
Fixes #13290 Change-Id: I0f7e7683d86db501cbedb6a0b7349ceb0769701c Reviewed-on: https://go-review.googlesource.com/32481 Reviewed-by: Martin Möhrmann <martisch@uos.de> Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
8380de416b
commit
b06c93e45b
|
|
@ -175,6 +175,10 @@ type Transport struct {
|
||||||
// If TLSNextProto is nil, HTTP/2 support is enabled automatically.
|
// If TLSNextProto is nil, HTTP/2 support is enabled automatically.
|
||||||
TLSNextProto map[string]func(authority string, c *tls.Conn) RoundTripper
|
TLSNextProto map[string]func(authority string, c *tls.Conn) RoundTripper
|
||||||
|
|
||||||
|
// ProxyConnectHeader optionally specifies headers to send to
|
||||||
|
// proxies during CONNECT requests.
|
||||||
|
ProxyConnectHeader Header
|
||||||
|
|
||||||
// MaxResponseHeaderBytes specifies a limit on how many
|
// MaxResponseHeaderBytes specifies a limit on how many
|
||||||
// response bytes are allowed in the server's response
|
// response bytes are allowed in the server's response
|
||||||
// header.
|
// header.
|
||||||
|
|
@ -1012,11 +1016,15 @@ func (t *Transport) dialConn(ctx context.Context, cm connectMethod) (*persistCon
|
||||||
}
|
}
|
||||||
case cm.targetScheme == "https":
|
case cm.targetScheme == "https":
|
||||||
conn := pconn.conn
|
conn := pconn.conn
|
||||||
|
hdr := t.ProxyConnectHeader
|
||||||
|
if hdr == nil {
|
||||||
|
hdr = make(Header)
|
||||||
|
}
|
||||||
connectReq := &Request{
|
connectReq := &Request{
|
||||||
Method: "CONNECT",
|
Method: "CONNECT",
|
||||||
URL: &url.URL{Opaque: cm.targetAddr},
|
URL: &url.URL{Opaque: cm.targetAddr},
|
||||||
Host: cm.targetAddr,
|
Host: cm.targetAddr,
|
||||||
Header: make(Header),
|
Header: hdr,
|
||||||
}
|
}
|
||||||
if pa := cm.proxyAuth(); pa != "" {
|
if pa := cm.proxyAuth(); pa != "" {
|
||||||
connectReq.Header.Set("Proxy-Authorization", pa)
|
connectReq.Header.Set("Proxy-Authorization", pa)
|
||||||
|
|
|
||||||
|
|
@ -3777,6 +3777,52 @@ func testTransportIDNA(t *testing.T, h2 bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Issue 13290: send User-Agent in proxy CONNECT
|
||||||
|
func TestTransportProxyConnectHeader(t *testing.T) {
|
||||||
|
defer afterTest(t)
|
||||||
|
reqc := make(chan *Request, 1)
|
||||||
|
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
|
||||||
|
if r.Method != "CONNECT" {
|
||||||
|
t.Errorf("method = %q; want CONNECT", r.Method)
|
||||||
|
}
|
||||||
|
reqc <- r
|
||||||
|
c, _, err := w.(Hijacker).Hijack()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Hijack: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.Close()
|
||||||
|
}))
|
||||||
|
defer ts.Close()
|
||||||
|
tr := &Transport{
|
||||||
|
ProxyConnectHeader: Header{
|
||||||
|
"User-Agent": {"foo"},
|
||||||
|
"Other": {"bar"},
|
||||||
|
},
|
||||||
|
Proxy: func(r *Request) (*url.URL, error) {
|
||||||
|
return url.Parse(ts.URL)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
defer tr.CloseIdleConnections()
|
||||||
|
c := &Client{Transport: tr}
|
||||||
|
res, err := c.Get("https://dummy.tld/") // https to force a CONNECT
|
||||||
|
if err == nil {
|
||||||
|
res.Body.Close()
|
||||||
|
t.Errorf("unexpected success")
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
case <-time.After(3 * time.Second):
|
||||||
|
t.Fatal("timeout")
|
||||||
|
case r := <-reqc:
|
||||||
|
if got, want := r.Header.Get("User-Agent"), "foo"; got != want {
|
||||||
|
t.Errorf("CONNECT request User-Agent = %q; want %q", got, want)
|
||||||
|
}
|
||||||
|
if got, want := r.Header.Get("Other"), "bar"; got != want {
|
||||||
|
t.Errorf("CONNECT request Other = %q; want %q", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var errFakeRoundTrip = errors.New("fake roundtrip")
|
var errFakeRoundTrip = errors.New("fake roundtrip")
|
||||||
|
|
||||||
type funcRoundTripper func()
|
type funcRoundTripper func()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue