mirror of
https://github.com/golang/go.git
synced 2025-10-19 19:13:18 +00:00
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 #57273 Change-Id: I84598f69608e95c1b556ea0ce5953ed43bf2d824 Reviewed-on: https://go-review.googlesource.com/c/go/+/710395 Auto-Submit: Damien Neil <dneil@google.com> Reviewed-by: Michael Pratt <mpratt@google.com> Reviewed-by: Damien Neil <dneil@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
parent
584a89fe74
commit
aced4c79a2
2 changed files with 46 additions and 5 deletions
|
@ -690,8 +690,7 @@ func (c *Client) do(req *Request) (retres *Response, reterr error) {
|
||||||
stripSensitiveHeaders = true
|
stripSensitiveHeaders = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
copyHeaders(req, stripSensitiveHeaders)
|
copyHeaders(req, stripSensitiveHeaders, !includeBody)
|
||||||
|
|
||||||
// Add the Referer header from the most recent
|
// Add the Referer header from the most recent
|
||||||
// request URL to the new one, if it's not https->http:
|
// 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 != "" {
|
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
|
// makeHeadersCopier makes a function that copies headers from the
|
||||||
// initial Request, ireq. For every redirect, this function must be called
|
// initial Request, ireq. For every redirect, this function must be called
|
||||||
// so that it can copy headers into the upcoming Request.
|
// 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.
|
// The headers to copy are from the very initial request.
|
||||||
// We use a closured callback to keep a reference to these original headers.
|
// We use a closured callback to keep a reference to these original headers.
|
||||||
var (
|
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
|
// If Jar is present and there was some initial cookies provided
|
||||||
// via the request header, then we may need to alter the initial
|
// via the request header, then we may need to alter the initial
|
||||||
// cookies as we follow redirects since each redirect may end up
|
// 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).
|
// (at least the safe ones).
|
||||||
for k, vv := range ireqhdr {
|
for k, vv := range ireqhdr {
|
||||||
sensitive := false
|
sensitive := false
|
||||||
|
body := false
|
||||||
switch CanonicalHeaderKey(k) {
|
switch CanonicalHeaderKey(k) {
|
||||||
case "Authorization", "Www-Authenticate", "Cookie", "Cookie2",
|
case "Authorization", "Www-Authenticate", "Cookie", "Cookie2",
|
||||||
"Proxy-Authorization", "Proxy-Authenticate":
|
"Proxy-Authorization", "Proxy-Authenticate":
|
||||||
sensitive = true
|
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
|
req.Header[k] = vv
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
// Issue 22233: copy host when Client follows a relative redirect.
|
||||||
func TestClientCopyHostOnRedirect(t *testing.T) { run(t, testClientCopyHostOnRedirect) }
|
func TestClientCopyHostOnRedirect(t *testing.T) { run(t, testClientCopyHostOnRedirect) }
|
||||||
func testClientCopyHostOnRedirect(t *testing.T, mode testMode) {
|
func testClientCopyHostOnRedirect(t *testing.T, mode testMode) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue