Skip to content

Commit aced4c7

Browse files
seankhliaogopherbot
authored andcommitted
net/http: strip request body headers on POST to GET redirects
According to WHATWG Fetch, when the body is dropped in a redirect, headers that describe the body should also be dropped. https://fetch.spec.whatwg.org/#http-redirect-fetch Fixes golang#57273 Change-Id: I84598f69608e95c1b556ea0ce5953ed43bf2d824 Reviewed-on: https://go-review.googlesource.com/c/go/+/710395 Auto-Submit: Damien Neil <[email protected]> Reviewed-by: Michael Pratt <[email protected]> Reviewed-by: Damien Neil <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent 584a89f commit aced4c7

File tree

2 files changed

+46
-5
lines changed

2 files changed

+46
-5
lines changed

src/net/http/client.go

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -690,8 +690,7 @@ func (c *Client) do(req *Request) (retres *Response, reterr error) {
690690
stripSensitiveHeaders = true
691691
}
692692
}
693-
copyHeaders(req, stripSensitiveHeaders)
694-
693+
copyHeaders(req, stripSensitiveHeaders, !includeBody)
695694
// Add the Referer header from the most recent
696695
// request URL to the new one, if it's not https->http:
697696
if ref := refererForURL(reqs[len(reqs)-1].URL, req.URL, req.Header.Get("Referer")); ref != "" {
@@ -758,7 +757,7 @@ func (c *Client) do(req *Request) (retres *Response, reterr error) {
758757
// makeHeadersCopier makes a function that copies headers from the
759758
// initial Request, ireq. For every redirect, this function must be called
760759
// so that it can copy headers into the upcoming Request.
761-
func (c *Client) makeHeadersCopier(ireq *Request) func(req *Request, stripSensitiveHeaders bool) {
760+
func (c *Client) makeHeadersCopier(ireq *Request) func(req *Request, stripSensitiveHeaders, stripBodyHeaders bool) {
762761
// The headers to copy are from the very initial request.
763762
// We use a closured callback to keep a reference to these original headers.
764763
var (
@@ -772,7 +771,7 @@ func (c *Client) makeHeadersCopier(ireq *Request) func(req *Request, stripSensit
772771
}
773772
}
774773

775-
return func(req *Request, stripSensitiveHeaders bool) {
774+
return func(req *Request, stripSensitiveHeaders, stripBodyHeaders bool) {
776775
// If Jar is present and there was some initial cookies provided
777776
// via the request header, then we may need to alter the initial
778777
// cookies as we follow redirects since each redirect may end up
@@ -810,12 +809,21 @@ func (c *Client) makeHeadersCopier(ireq *Request) func(req *Request, stripSensit
810809
// (at least the safe ones).
811810
for k, vv := range ireqhdr {
812811
sensitive := false
812+
body := false
813813
switch CanonicalHeaderKey(k) {
814814
case "Authorization", "Www-Authenticate", "Cookie", "Cookie2",
815815
"Proxy-Authorization", "Proxy-Authenticate":
816816
sensitive = true
817+
818+
case "Content-Encoding", "Content-Language", "Content-Location",
819+
"Content-Type":
820+
// Headers relating to the body which is removed for
821+
// POST to GET redirects
822+
// https://fetch.spec.whatwg.org/#http-redirect-fetch
823+
body = true
824+
817825
}
818-
if !(sensitive && stripSensitiveHeaders) {
826+
if !(sensitive && stripSensitiveHeaders) && !(body && stripBodyHeaders) {
819827
req.Header[k] = vv
820828
}
821829
}

src/net/http/client_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1621,6 +1621,39 @@ func testClientStripHeadersOnRepeatedRedirect(t *testing.T, mode testMode) {
16211621
}
16221622
}
16231623

1624+
func TestClientStripHeadersOnPostToGetRedirect(t *testing.T) {
1625+
run(t, testClientStripHeadersOnPostToGetRedirect)
1626+
}
1627+
func testClientStripHeadersOnPostToGetRedirect(t *testing.T, mode testMode) {
1628+
ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
1629+
if r.Method == "POST" {
1630+
Redirect(w, r, "/redirected", StatusFound)
1631+
return
1632+
} else if r.Method != "GET" {
1633+
t.Errorf("unexpected request method: %v", r.Method)
1634+
return
1635+
}
1636+
for key, val := range r.Header {
1637+
if strings.HasPrefix(key, "Content-") {
1638+
t.Errorf("unexpected request body header after redirect: %v: %v", key, val)
1639+
}
1640+
}
1641+
})).ts
1642+
1643+
c := ts.Client()
1644+
1645+
req, _ := NewRequest("POST", ts.URL, strings.NewReader("hello world"))
1646+
req.Header.Set("Content-Encoding", "a")
1647+
req.Header.Set("Content-Language", "b")
1648+
req.Header.Set("Content-Length", "c")
1649+
req.Header.Set("Content-Type", "d")
1650+
res, err := c.Do(req)
1651+
if err != nil {
1652+
t.Fatal(err)
1653+
}
1654+
defer res.Body.Close()
1655+
}
1656+
16241657
// Issue 22233: copy host when Client follows a relative redirect.
16251658
func TestClientCopyHostOnRedirect(t *testing.T) { run(t, testClientCopyHostOnRedirect) }
16261659
func testClientCopyHostOnRedirect(t *testing.T, mode testMode) {

0 commit comments

Comments
 (0)