-
Notifications
You must be signed in to change notification settings - Fork 18k
net/http: flush after writing 101 header shouldn't send headers again #59564
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Writing a 101 Switching Protocols header indicates that what follows on the connection is no longer HTTP. The net/http server doesn't have any specific handling for Prior to Go 1.19, |
I wonder if it should 🤔 Which basically would mean that a subsequent
Just to clarify for me, with "refuse to write any further data to the connection" you mean without having hijacked it?
I believe this to be true, because it "used to work" for us.
EDIT: We actually do hijack after calling
That or conditionally flush are our options for a workaround. Both some suboptimal and I think it would be great for net/http to support 101 Switching Protocols in a sense that after the |
Digging into this some more, while the pre-1.19 Since the previous behavior was clearly intentional (and pretty much exactly what we seem to agree is reasonable), I think this is a regression even though that behavior wasn't documented. |
Change https://go.dev/cl/485775 mentions this issue: |
@neild thanks for the responsive fix 🎉 I think that's it and I guess this issue can be closed? |
Prior to Go 1.19 adding support for sending 1xx informational headers with ResponseWriter.WriteHeader, WriteHeader(101) would send a 101 status and disable further writes to the response. This behavior was not documented, but is intentional: Writing to the response body explicitly checks to see if a 101 status has been sent before writing. Restore the pre-1.19 behavior when writing a 101 Switching Protocols header: The header is sent, no subsequent headers are sent, and subsequent writes to the response body fail. For #59564 Change-Id: I72c116f88405b1ef5067b510f8c7cff0b36951ee Reviewed-on: https://go-review.googlesource.com/c/go/+/485775 Reviewed-by: Bryan Mills <[email protected]> Auto-Submit: Damien Neil <[email protected]> Run-TryBot: Damien Neil <[email protected]> TryBot-Result: Gopher Robot <[email protected]>
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
The change set https://go-review.googlesource.com/c/go/+/269997 (#26089, #36734) for Go 1.19 introduced that for all 1xx status codes the headers are persisted for subsequent writes - my assumption is that this is mostly for
100 Continue
.However, when we do a
w.WriteHeader(http.StatusSwitchingProtocols)
(status code is101
here) the internalw.wroteHeader
isn't set to true (due to the early return in theif
for1xx
responses.:go/src/net/http/server.go
Line 1176 in bc5b194
... this leads to another
w.WriteHeader(http.StatusOK)
in a subsequentFlush
:go/src/net/http/server.go
Line 1713 in bc5b194
... which is not my expectation here. A subsequent flush for (at least) a
101
response should just flush / no-op without sending thathttp.StatusOK
+ headers.Note: if I have some time I'll try to create a unit test ..., but here is an exploratory example:
Then e.g. run
curl -v localhost:3030
and observe the verbose output, or usetelnet localhost 3030
to make a manual request and check the raw TCP output:... as you can see the second
HTTP/1.1 200 OK
response is not expected.What did you expect to see?
That a subsequent flush after
w.WriteHeader(http.StatusSwitchingProtocols)
doesn't do aw.WriteHeader(http.StatusOk)
.What did you see instead?
A subsequent flush after
w.WriteHeader(http.StatusSwitchingProtocols)
does aw.WriteHeader(http.StatusOk)
.The text was updated successfully, but these errors were encountered: