-
Notifications
You must be signed in to change notification settings - Fork 18.3k
Description
Go version
go version go1.24.4 linux/amd64
Output of go env
in your module/workspace:
AR='ar'
CC='gcc'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='g++'
GCCGO='gccgo'
GO111MODULE=''
GOAMD64='v1'
GOARCH='amd64'
GOAUTH='netrc'
GOBIN=''
GOCACHE='/home/<name>/.cache/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/home/<name>/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build456588333=/tmp/go-build -gno-record-gcc-switches'
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMOD='/dev/null'
GOMODCACHE='/home/<name>/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/home/<name>/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/home/<name>/goinstall'
GOSUMDB='sum.golang.org'
GOTELEMETRY='local'
GOTELEMETRYDIR='/home/<name>/.config/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/home/<name>/goinstall/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.24.4'
GOWORK=''
PKG_CONFIG='pkg-config'
What did you do?
I'm not sure if I should file this as a bug or a change request.
The http.Client
does not (always) forward cookies set during redirects. If there is a chain of redirects, the server can sent cookies during any of those. If I switch domains in a redirect chain, e.g.
http://127.0.0.1/first
-> response sets cookiehttp://127.0.1.1/second
http://127.0.0.1/third
-> does not receive the cookie
then the cookie won't be forwarded from response 1 to request 3.
This behaviour differs from Chrome, Firefox and curl (with --cookie-jar <file>
), who all forward the cookie from response 1 to request 3.
The Go net/http docs say something about this case, but I can't wrap my head around it. Might not work as expected when going back and forth between domains.
when forwarding the "Cookie" header with a non-nil cookie Jar. Since each redirect may mutate the state of the cookie jar, a redirect may possibly alter a cookie set in the initial request. When forwarding the "Cookie" header, any mutated cookies will be omitted, with the expectation that the Jar will insert those mutated cookies with the updated values (assuming the origin matches). If Jar is nil, the initial cookies are forwarded without change.
jar, _ := cookiejar.New(nil)
initCookie := &http.Cookie{
Name: "client-init",
Value: "hello",
}
initURL, _ := url.Parse("http://localhost:8080/")
jar.SetCookies(initURL, []*http.Cookie{initCookie})
client := &http.Client{Jar: jar}
resp, err := client.Get("http://localhost:8080/first")
#4800 mentions RFC 9110 but I don't see any obvious mandate of either behaviour. I'm not familiar with web RFCs though.
Sample webserver to try out different clients:
package main
import (
"fmt"
"log"
"net/http"
"os"
)
func printRequestInfo(r *http.Request) {
fmt.Printf("Request URL: %s; Cookies: %v\n", r.URL.String(), r.Cookies())
}
func main() {
hostname, err := os.Hostname()
if err != nil {
log.Fatalf("Error getting hostname: %v", err)
}
first := func(w http.ResponseWriter, r *http.Request) {
printRequestInfo(r)
cookie := &http.Cookie{
Name: "server-test",
Value: "set",
SameSite: http.SameSiteStrictMode,
Path: "/",
Secure: true,
HttpOnly: true,
}
http.SetCookie(w, cookie)
fmt.Printf("Setting cookie: %s=%s\n", cookie.Name, cookie.Value)
url := "http://" + hostname + ":8080/second"
http.Redirect(w, r, url, http.StatusFound)
}
second := func(w http.ResponseWriter, r *http.Request) {
printRequestInfo(r)
url := "http://localhost:8080/third"
http.Redirect(w, r, url, http.StatusFound)
}
third := func(w http.ResponseWriter, r *http.Request) {
printRequestInfo(r)
w.WriteHeader(http.StatusOK)
}
http.HandleFunc("/first", first)
http.HandleFunc("/second", second)
http.HandleFunc("/third", third)
listenAddr := "0.0.0.0:8080"
fmt.Printf("Listening on %s\n", listenAddr)
if err := http.ListenAndServe(listenAddr, nil); err != nil {
log.Fatal(err)
}
}
What did you see happen?
Server log of Go client:
Request URL: /first; Cookies: [client-init=hello]
Setting cookie: server-test=set
Request URL: /second; Cookies: []
Request URL: /third; Cookies: [client-init=hello]
What did you expect to see?
Chrome:
Request URL: /first; Cookies: []
Setting cookie: server-test=set
Request URL: /second; Cookies: []
Request URL: /third; Cookies: [server-test=set]
curl --location --cookie-jar ./jar localhost:8080/first
:
Request URL: /first; Cookies: []
Setting cookie: server-test=set
Request URL: /second; Cookies: []
Request URL: /third; Cookies: [server-test=set]