Better HTTP/1 connection reuse in Go 1.27 (go.dev)
giancarlostoro 2 hours ago
gandreani 3 hours ago
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 4 hours ago
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.
aleksi 4 hours ago
> Note, however, that Transport will automatically try to read a Response Body to EOF asynchronously up to a conservative limit when a Body is closed.
Similar wording appears in a few other places; search for “asynchronously”.
jerf 4 hours ago
jchw 4 hours ago
0x696C6961 2 hours ago
hnav 2 hours ago
rkuska 4 hours ago
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.
gandreani 3 hours ago
hnav 2 hours ago
https://cs.opensource.google/go/go/+/refs/tags/go1.27.2:src/...
What it won't do looking at the code is handle streamed responses over transfer-encoding:chunked which means that if the other end is doing
json.NewEncoder(responseWriter).Encode(&someStruct)
this optimization won't do anything.hxtk an hour ago
The standard library maintainers recognized this as a problem that there was no “better,” more convenient way to do it and in encoding/json/v2 they have UnmarshalRead for that use case: https://pkg.go.dev/encoding/json/v2#UnmarshalRead
jamesponddotco 5 hours ago
[1]: https://github.com/cipherdothost/x-go/blob/caa562ded82b8c417...
aleksi 4 hours ago
jamesponddotco 4 hours ago
Not because of the copy itself, since a little copy is better than a little dependency, as they say, but because it was a pain to update everything when I inevitably found a bug in what I copied.
nasretdinov 5 hours ago
prussian 4 hours ago
donatj 4 hours ago
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?
80fj0348i 4 hours ago
giovannibajo1 4 hours ago
MrDOS 4 hours ago
seki285 3 hours ago
trgn 3 hours ago
afavour 3 hours ago
nasretdinov 3 hours ago
cyberax 3 hours ago
hnav 2 hours ago
sock.write('HTTP/1.1 200 OK\r\ncontent-length: ' + f.size() + '\r\n\r\n')
sendfile(sock, f)
which wouldn't work with H2/H3. WebSockets are still in practice H/1 only (spec exists but is disabled in browsers). Another aspect is that if you're simply using HTTP as a preamble to 1 large (bidi) pipe, the extra framing and flow control of H/2 is just a performance handicap.siren2026 2 hours ago