Repository navigation
fix: skip body read when Dial fails after a 101 response - #591
Conversation
b973a9f to
a2fa86f
Compare
When the server answered 101 but a header check failed, Dial read up to 1024 bytes from the response body before returning. After a 101 the body is the upgraded connection, so a silent server made Dial wait for the 3 s timer. Close it instead and return an empty body; other statuses still return the first 1024 bytes.
a2fa86f to
e4d658a
Compare
This comment has been minimized.
This comment has been minimized.
|
Chat: Review posted | View chat Review historydeep-review v0.13.0 | Round 3 | Last posted: Round 3, 4 findings (1 P3, 3 P4), APPROVE. Review Finding inventoryFindings
Downgrade and drop reasoning (R1)
Downgrade and drop reasoning (R3)
Contested and acknowledgedNone. Round logRound 1Netero first pass: no findings, 1 Note (CRF-1). Law not run (effective +67). Full panel, round 1: ging-go, ryosuke, killua, melody (specialists: Go code, connection and HTTP body lifecycle), pariston, mafuuu (core), bisky (tests), gon, leorio (once-per-PR floor), chopper (wildcard). Size 10 exceeds the focused target of 6-8 because four specialists (ging-go, ryosuke, killua, melody) plus the Gon and Leorio floor were required. Orchestrator verified CRF-2: with the server writing "after upgrade" after the 101 headers, head passes and base fails. 1 P3, 3 P4 posted; 2 Notes and 5 out-of-scope items in body; 5 dropped. Reviewed against e1a21e5..e4d658a. Round 2 updateBLOCKED. CRF-7 silent (no doc change, no reply). CRF-2, CRF-4, CRF-6 author fixed, unverified by panel. No review. Reviewed against e1a21e5..d967226. Round 3Churn guard PROCEED (CRF-7 addressed in 1abc068). Fix round (only comments, doc, and test data changed since R1 panel; no files added, no signature changes). Netero: no findings; verified base dial.go fails the new test on the body assertion. Panel: bisky, gon, leorio (raised CRF-2, CRF-4, CRF-6, CRF-7), ging-go, ryosuke (.go files), chopper (wildcard). CRF-2, CRF-4, CRF-6, CRF-7 fixes verified by panel. Gon raised 3 P2 wording items and 1 Note, all dropped (CRF-17 to CRF-20). No open findings. Reviewed against e1a21e5..1abc068. About deep-reviewCRF = Coder Review Finding (P0-P4, Nit, Note)
|
With a silent server, an empty body also results from reading the upgraded connection with a short timer. Bytes after the 101 make that variant fail on the body check.
The read is bounded by the 3 s timer, so "waits for data the server may never send" overstated it.
This comment has been minimized.
This comment has been minimized.
The read also stalls when the server sends fewer than 1024 bytes and keeps the connection open, not only when it sends nothing.
The Dial doc said the body on error holds up to 1024 bytes, so a caller debugging a failed 101 could not tell an empty body from a silent server.
When the server answers
101 Switching Protocolsbut the handshake still fails, for example on an invalidSec-WebSocket-Acceptor a subprotocol the client did not offer,Dialnow closes the response body and returns at once.Previously, every
Dialthat failed after receiving a response read up to 1024 bytes of the response body for debugging, with a 3 second timer. After a 101 the body is the upgraded connection, not an HTTP body, so when the server sent nothing more, each of these failures took 3 seconds.For these failures the returned response keeps its status and headers, and
resp.Bodyis empty (http.NoBody). Failures with any other status are unchanged:resp.Bodyholds up to the first 1024 bytes, read with the same 3 second limit.The tradeoff: if a server answers 101 and then writes error text on the connection,
resp.Bodyno longer contains that text. Bytes after a 101 belong to the upgraded protocol, not to an HTTP body.TestDialFailedHandshakeBodycovers a 101 with an invalidSec-WebSocket-Acceptfrom a server that then sends a few bytes and keeps the connection open (fails on master after 3.0 s with those bytes in the body; passes with this change in about 0 s against a 1 s limit) and a 403 whose body is still returned. Lint, race tests and the WASM test pass.Decision log
http.NoBodyinstead of a nilresp.Body: whenDialreturns a response with an error,resp.Bodyhas never been nil, so callers that read it need no new nil check.Dialdoc now says the body is empty after a 101. Its old text ("you can only read the first 1024 bytes of the body") stayed literally true, but a caller debugging a failed 101 could not tell an empty body from a silent server.