You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
net.http: stream response callbacks and stop limits over HTTP/2 (#27369)
* net.http: stream response callbacks and stop limits over HTTP/2 (closes#27368)
The HTTP/2 fetch path (#27362) buffered the entire response body, so requests
using on_progress / on_progress_body / stop_copying_limit / stop_receiving_limit
were forced onto HTTP/1.1. This adds real streaming support so they work on the
HTTP/2 path too.
- New H2ClientRequest fields: on_data (per-DATA-frame callback) and
stop_copying_limit / stop_receiving_limit, mirroring the HTTP/1.1 semantics.
- H2Conn.read_response now tracks cumulative body bytes, reads Content-Length
if present, fires on_data per DATA frame (including chunk, cumulative
body_so_far, content-length, and status), respects stop_copying_limit
(caps the response body while still firing callbacks and draining the
stream), and respects stop_receiving_limit (breaks the read loop early).
- The h2_do shim in backend.c.v adapts the Request's on_progress and
on_progress_body into a single H2DataFn closure and threads the two stop
limits through. The previous gate (uses_response_streaming) is removed, and
the enable_http2 docs note that on_progress fires per DATA payload on h2
rather than per raw network read.
Tests over the in-memory transport assert: on_data fires per DATA frame with
cumulative body_so_far, Content-Length (when present), and status;
stop_copying_limit caps the response body while callbacks keep firing across
all chunks; stop_receiving_limit breaks the loop early. Verified end-to-end
against https://www.google.com/ — http.fetch(enable_http2: true,
on_progress_body: f) reports HTTP/2.0, status 200, and the on_progress_body
callback fires once per 16 KiB DATA frame with cumulative bytes matching the
final body length. Passes under -W -cstrict -cc clang.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* net.http: RST_STREAM(CANCEL) and mark H2Conn unusable on early termination
When stop_receiving_limit triggered, the response stream was left open without
sending RST_STREAM. On a reused H2Conn the peer's in-flight DATA frames for the
abandoned stream would still arrive, consuming the connection-level receive
window and risking starvation of subsequent requests.
Fix: when bailing early, send RST_STREAM with error code CANCEL on the request
stream (RFC 7540 Section 8.1.4 / 5.4.2) so the peer stops sending more DATA,
and set a new H2Conn.aborted flag so subsequent H2Conn.do() calls return a
clear error rather than proceeding on a half-drained connection.
Strengthens the stop_receiving_limit test to assert the client emitted
RST_STREAM(CANCEL) on the request stream and that a second do() on the same
connection errors out.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---------
Co-authored-by: Richard Wheeler <quaesitor.scientiam@gmail.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
0 commit comments