Commit 35ffbab
net.http: add server-side HTTP/2 (ALPN + h2 frame demux) (#27382)
* net.http: add server-side HTTP/2 (ALPN + h2 frame demux)
Build on TLS termination (#27373) to let net.http.Server speak HTTP/2.
- New `enable_http2` field on Server. When set on a TLS listener, the listener
advertises ALPN `h2, http/1.1`. After the handshake, the TLS worker checks
`negotiated_alpn()`: if `h2`, it dispatches to the new HTTP/2 driver;
otherwise the existing HTTP/1.1 path is unchanged.
- New h2_server.v (H2ServerConn): reads the client preface, exchanges SETTINGS
(advertising SETTINGS_MAX_CONCURRENT_STREAMS=1 so requests serialize), and
runs the frame loop. HEADERS+CONTINUATION are assembled and HPACK-decoded
into a net.http.Request; DATA frames populate the body and replenish flow
control; SETTINGS / PING / WINDOW_UPDATE / GOAWAY / RST_STREAM / PRIORITY are
serviced inline. When the request stream closes, the existing
Handler.handle(Request) Response interface is invoked unchanged; the Response
is HPACK-encoded into HEADERS + DATA(END_STREAM) and sent back.
- Hop-by-hop response headers are dropped (RFC 7540 Section 8.1.2.2). The
request body is capped at 8 MiB with RST_STREAM(REFUSED_STREAM) on overflow.
- The Handler contract is untouched: req.url is the request-target (the :path
pseudo-header) and Host comes from :authority, so existing HTTP/1.1 handlers
run with no changes on the new transport.
Tests: h2_server_test.v drives the server through an in-memory blocking pipe
with the existing HTTP/2 client (GET, POST with a body, non-200 status, all
round-trip). server_tls_test.v adds a TLS + ALPN end-to-end test asserting
http.fetch(enable_http2: true) negotiates h2 against the same listener that
still serves HTTP/1.1 to non-h2 clients. Full vlib/net/http suite is green on
both backends; passes under -W -cstrict -cc clang.
This is opt-in and additive: with enable_http2 unset (or for non-TLS servers),
behaviour is exactly as before. Stream multiplexing with a background reader is
a planned follow-up (this driver serializes requests).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* net.http: server-side h2 send flow control + gate Windows ALPN test
Address two findings from review of the server-side HTTP/2 PR:
- Server response DATA now respects the HTTP/2 send flow-control windows
(RFC 7540 Section 6.9). send_body bounds each DATA frame by
min(connection, stream) window, decrements both after sending, and waits for
WINDOW_UPDATE (servicing SETTINGS / PING / WINDOW_UPDATE, and a RST_STREAM for
the stream being written) when a window is exhausted. apply_settings now also
adjusts every active stream's send window by the delta when the peer changes
SETTINGS_INITIAL_WINDOW_SIZE (Section 6.9.2). Previously a client that lowered
its initial window could be sent more DATA than permitted and reset the stream
with FLOW_CONTROL_ERROR.
- Gate test_server_tls_h2_negotiation so it skips on the default Windows
configuration: the SChannel client does not advertise ALPN, so it cannot
negotiate HTTP/2 and the version assertion would fail. The path stays covered
with `-d no_vschannel` (mbedtls client), matching how the rest of the suite
treats the SChannel limitation.
Adds test_h2_server_respects_send_window: a raw client advertises
SETTINGS_INITIAL_WINDOW_SIZE=10, and the test asserts the server's first DATA
frame is <= 10 bytes and that the full 100-byte body is delivered after a
WINDOW_UPDATE.
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>1 parent e381c3e commit 35ffbab
5 files changed
Lines changed: 915 additions & 0 deletions
File tree
- vlib/net/http
0 commit comments