From: Sean Liao Date: Wed, 8 Oct 2025 21:33:24 +0000 (+0100) Subject: net/http: set cookie host to Request.Host when available X-Git-Tag: go1.26rc1~644 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=69e82796322bbff60b522534a8a6eacb2bf1ebba;p=gostls13.git net/http: set cookie host to Request.Host when available When both Request.URL and Request.Host are set, the host in URL is used for connecting at the transport level, while Host is used for the request host line. Cookies should be set for the request, not the underlying connection destination. Fixes #38988 Change-Id: I09053b87ccac67081f6038d205837d9763701526 Reviewed-on: https://go-review.googlesource.com/c/go/+/710335 Reviewed-by: Damien Neil Auto-Submit: Damien Neil Reviewed-by: Michael Pratt LUCI-TryBot-Result: Go LUCI --- diff --git a/src/net/http/client.go b/src/net/http/client.go index ba095ea1e3..8faab2b17a 100644 --- a/src/net/http/client.go +++ b/src/net/http/client.go @@ -172,8 +172,13 @@ func refererForURL(lastReq, newReq *url.URL, explicitRef string) string { // didTimeout is non-nil only if err != nil. func (c *Client) send(req *Request, deadline time.Time) (resp *Response, didTimeout func() bool, err error) { + cookieURL := req.URL + if req.Host != "" { + cookieURL = cloneURL(cookieURL) + cookieURL.Host = req.Host + } if c.Jar != nil { - for _, cookie := range c.Jar.Cookies(req.URL) { + for _, cookie := range c.Jar.Cookies(cookieURL) { req.AddCookie(cookie) } } @@ -183,7 +188,7 @@ func (c *Client) send(req *Request, deadline time.Time) (resp *Response, didTime } if c.Jar != nil { if rc := resp.Cookies(); len(rc) > 0 { - c.Jar.SetCookies(req.URL, rc) + c.Jar.SetCookies(cookieURL, rc) } } return resp, nil, nil diff --git a/src/net/http/client_test.go b/src/net/http/client_test.go index 94fddb508e..2a3ee385f3 100644 --- a/src/net/http/client_test.go +++ b/src/net/http/client_test.go @@ -585,6 +585,36 @@ var echoCookiesRedirectHandler = HandlerFunc(func(w ResponseWriter, r *Request) } }) +func TestHostMismatchCookies(t *testing.T) { run(t, testHostMismatchCookies) } +func testHostMismatchCookies(t *testing.T, mode testMode) { + ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) { + for _, c := range r.Cookies() { + c.Value = "SetOnServer" + SetCookie(w, c) + } + })).ts + + reqURL, _ := url.Parse(ts.URL) + hostURL := *reqURL + hostURL.Host = "cookies.example.com" + + c := ts.Client() + c.Jar = new(TestJar) + c.Jar.SetCookies(reqURL, []*Cookie{{Name: "First", Value: "SetOnClient"}}) + c.Jar.SetCookies(&hostURL, []*Cookie{{Name: "Second", Value: "SetOnClient"}}) + + req, _ := NewRequest("GET", ts.URL, NoBody) + req.Host = hostURL.Host + resp, err := c.Do(req) + if err != nil { + t.Fatalf("Get: %v", err) + } + resp.Body.Close() + + matchReturnedCookies(t, []*Cookie{{Name: "First", Value: "SetOnClient"}}, c.Jar.Cookies(reqURL)) + matchReturnedCookies(t, []*Cookie{{Name: "Second", Value: "SetOnServer"}}, c.Jar.Cookies(&hostURL)) +} + func TestClientSendsCookieFromJar(t *testing.T) { defer afterTest(t) tr := &recordingTransport{}