aboutsummaryrefslogtreecommitdiff
path: root/src/net/http
diff options
context:
space:
mode:
Diffstat (limited to 'src/net/http')
-rw-r--r--src/net/http/client.go18
-rw-r--r--src/net/http/client_test.go33
2 files changed, 46 insertions, 5 deletions
diff --git a/src/net/http/client.go b/src/net/http/client.go
index 8faab2b17a..d6a8010735 100644
--- a/src/net/http/client.go
+++ b/src/net/http/client.go
@@ -690,8 +690,7 @@ func (c *Client) do(req *Request) (retres *Response, reterr error) {
stripSensitiveHeaders = true
}
}
- copyHeaders(req, stripSensitiveHeaders)
-
+ copyHeaders(req, stripSensitiveHeaders, !includeBody)
// Add the Referer header from the most recent
// request URL to the new one, if it's not https->http:
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) {
// makeHeadersCopier makes a function that copies headers from the
// initial Request, ireq. For every redirect, this function must be called
// so that it can copy headers into the upcoming Request.
-func (c *Client) makeHeadersCopier(ireq *Request) func(req *Request, stripSensitiveHeaders bool) {
+func (c *Client) makeHeadersCopier(ireq *Request) func(req *Request, stripSensitiveHeaders, stripBodyHeaders bool) {
// The headers to copy are from the very initial request.
// We use a closured callback to keep a reference to these original headers.
var (
@@ -772,7 +771,7 @@ func (c *Client) makeHeadersCopier(ireq *Request) func(req *Request, stripSensit
}
}
- return func(req *Request, stripSensitiveHeaders bool) {
+ return func(req *Request, stripSensitiveHeaders, stripBodyHeaders bool) {
// If Jar is present and there was some initial cookies provided
// via the request header, then we may need to alter the initial
// 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
// (at least the safe ones).
for k, vv := range ireqhdr {
sensitive := false
+ body := false
switch CanonicalHeaderKey(k) {
case "Authorization", "Www-Authenticate", "Cookie", "Cookie2",
"Proxy-Authorization", "Proxy-Authenticate":
sensitive = true
+
+ case "Content-Encoding", "Content-Language", "Content-Location",
+ "Content-Type":
+ // Headers relating to the body which is removed for
+ // POST to GET redirects
+ // https://fetch.spec.whatwg.org/#http-redirect-fetch
+ body = true
+
}
- if !(sensitive && stripSensitiveHeaders) {
+ if !(sensitive && stripSensitiveHeaders) && !(body && stripBodyHeaders) {
req.Header[k] = vv
}
}
diff --git a/src/net/http/client_test.go b/src/net/http/client_test.go
index 2a3ee385f3..d184f72031 100644
--- a/src/net/http/client_test.go
+++ b/src/net/http/client_test.go
@@ -1621,6 +1621,39 @@ func testClientStripHeadersOnRepeatedRedirect(t *testing.T, mode testMode) {
}
}
+func TestClientStripHeadersOnPostToGetRedirect(t *testing.T) {
+ run(t, testClientStripHeadersOnPostToGetRedirect)
+}
+func testClientStripHeadersOnPostToGetRedirect(t *testing.T, mode testMode) {
+ ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
+ if r.Method == "POST" {
+ Redirect(w, r, "/redirected", StatusFound)
+ return
+ } else if r.Method != "GET" {
+ t.Errorf("unexpected request method: %v", r.Method)
+ return
+ }
+ for key, val := range r.Header {
+ if strings.HasPrefix(key, "Content-") {
+ t.Errorf("unexpected request body header after redirect: %v: %v", key, val)
+ }
+ }
+ })).ts
+
+ c := ts.Client()
+
+ req, _ := NewRequest("POST", ts.URL, strings.NewReader("hello world"))
+ req.Header.Set("Content-Encoding", "a")
+ req.Header.Set("Content-Language", "b")
+ req.Header.Set("Content-Length", "c")
+ req.Header.Set("Content-Type", "d")
+ res, err := c.Do(req)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer res.Body.Close()
+}
+
// Issue 22233: copy host when Client follows a relative redirect.
func TestClientCopyHostOnRedirect(t *testing.T) { run(t, testClientCopyHostOnRedirect) }
func testClientCopyHostOnRedirect(t *testing.T, mode testMode) {