Better HTTP/1 connection reuse in Go 1.27

169 points - today at 4:29 PM

Source

Comments

giancarlostoro today at 8:43 PM
I do wonder when they'll add http/3 into the stdlib. Go having simple but powerful / capable out of the box support for http is one of the key things it had that made it get farther than it could have had it not included such a strong OOTB standard library. I feel like it would have still exploded but not quite as quickly, there's just something about building full web apps with no third party packages using only what's out of the box with Go itself, the only other "language" that I ever felt this way with was probably PHP, although Racket might be another, since I don't think I need to go out of my way to setup anything to do web dev with Racket.
gandreani today at 7:12 PM
I find it kind of amusing to consider that the go team didn't commit to implement this automatic connection re-use until they probably encountered in the wild the horrible but correct third iteration of drainAndCloseBody.

1. Suggest drainAndCloseBody // Team: this is reasonable

2. Implement drainAndCloseBodyWithTimer // Team: no problems here

3. then drainAsyncAndCloseBodyWithTimer // Team: a bit wordy but no problem here

4. Someone at google uses 3. with an http/2 connection // Team: this is where we draw the line?

I sympathize with the struggle of following golang's mission to be simple when you consider this common but tricky edge case. Iteration 3 makes sense but by gosh is it ugly ha.

jerf today at 6:03 PM
Am I missing something or is none of this information documented in net/http itself? This is a surprising implementation of "Close" and should be documented somewhere.

I can attest to the fact this is a Frequently Asked Question among people who are trying to Go as an HTTP client, so even though this feels somewhat icky, I can understand where it is coming from. However, I'm also missing, if I want to slam this connection closed, which is a reasonable thing to want, how do I do that without uselessly draining a socket I don't intend to reuse? Fake the "Connection: close" header into the Response object? Hope I can dig out an underlying socket of some sort under the concrete type of the Body.Response that I can bypass this code with? Seems like there should be a way to do that too.

rkuska today at 6:12 PM
Now if you use json’s Decoder you can read a body and still might end up without reused connection - if a response contains a newline.

Decoder only reads X bytes (512? I don’t remember) and if the structure fits into these bytes exactly (and the multiplications of it) the newline leaves hanging there.

I always check for Decoder.More (this drains whitespace) after decoding.

jamesponddotco today at 5:27 PM
I can finally retire xhttp.DrainResponseBody[1], which I just learned, wasn’t doing that good of a job anyway.

[1]: https://github.com/cipherdothost/x-go/blob/caa562ded82b8c417...

nasretdinov today at 5:45 PM
It sucks that this changes the behaviour under the hood that you previously coukd rely on the fact that closing the response body lets you skip downloading the HTTP body entirely, but I do like the tradeoff here, since it also limits the download time to just 50ms you'd not get overwhelmed if your network can't keep up with all the cancelled HTTP bodies, you'll just wait a little bit of traffic instead.
prussian today at 5:50 PM
At the very end it mentions it won't drain bodies for Connection: close Does this work with reverse proxies? I've had issues with nginx still getting IO errors when my server doesn't consume bodies and bubbling them up as 5xx codes to the client. I believe I've seen this with Firefox as well, where XHR status codes would be 0. Early closing, without consuming body, seems to work as expected with Chrome and curl though.
donatj today at 6:23 PM
> Using HTTP/1 (GODEBUG=http2client=0), calling this function 100 times against index.golang.org takes ~710 milliseconds on Go 1.26 on my machine. On Go 1.27, the same program takes ~150 milliseconds.

Does this mean I need to disable http2 for this to work or is that just a further proof that http2 isn't actually being used?

seki285 today at 6:50 PM
Any reason to be still using HTTP/1 in 2026?
mozidlb0e29352 today at 6:30 PM
[flagged]