diff --git a/client_test.go b/client_test.go index df00b2b2..83123093 100644 --- a/client_test.go +++ b/client_test.go @@ -329,6 +329,17 @@ func TestRedirect(t *testing.T) { _, err = tc().SetRedirectPolicy(AllowedDomainRedirectPolicy("localhost", "127.0.0.1")).R().Get("/redirect-to-other") assertNotNil(t, err) assertContains(t, err.Error(), "redirect domain [dummy.local] is not allowed", true) + + c := tc().SetRedirectPolicy(AlwaysCopyHeaderRedirectPolicy("Authorization")) + newHeader := make(http.Header) + oldHeader := make(http.Header) + oldHeader.Set("Authorization", "test") + c.GetClient().CheckRedirect(&http.Request{ + Header: newHeader, + }, []*http.Request{&http.Request{ + Header: oldHeader, + }}) + assertEqual(t, "test", newHeader.Get("Authorization")) } func TestGetTLSClientConfig(t *testing.T) { diff --git a/redirect.go b/redirect.go index 06ce5a6e..4f3b71e9 100644 --- a/redirect.go +++ b/redirect.go @@ -103,3 +103,26 @@ func getDomain(host string) string { ss = ss[1:] return strings.Join(ss, ".") } + +// AlwaysCopyHeaderRedirectPolicy ensures that the given sensitive headers will +// always be copied on redirect. +// By default, golang will copy all of the original request's headers on redirect, +// unless they're sensitive, like "Authorization" or "Www-Authenticate". Only send +// sensitive ones to the same origin, or subdomains thereof (https://go-review.googlesource.com/c/go/+/28930/) +// Check discussion: https://github.com/golang/go/issues/4800 +// For example: +// client.SetRedirectPolicy(req.AlwaysCopyHeaderRedirectPolicy("Authorization")) +func AlwaysCopyHeaderRedirectPolicy(headers ...string) RedirectPolicy { + return func(req *http.Request, via []*http.Request) error { + for _, header := range headers { + if len(req.Header.Values(header)) > 0 { + continue + } + vals := via[0].Header.Values(header) + for _, val := range vals { + req.Header.Add(header, val) + } + } + return nil + } +}