feat(network): poll-driven HTTP server and client over TcpNetwork - #133
Merged
Conversation
Introduce flux_network::http::HttpNetwork, a single-event-loop HTTP/1.x layer on top of TcpNetwork. One instance can listen for inbound requests and maintain persistent outbound endpoints; parsed requests and responses are delivered borrowed through poll_with, and responses may be deferred across polls (one pending request per connection, pipelining buffered). Server side supports Content-Length request bodies, automatic Expect: 100-continue, HEAD semantics, keep-alive/close negotiation, and protocol errors (400/413/431/501) handled before user code. Client side supports Content-Length, chunked, and EOF-delimited response bodies with interim-response skipping. Head/body/header-count limits and an idle timeout for accepted connections are configurable. To carry HTTP on the wire, TcpNetwork gains a per-group Framing choice: the existing length-prefixed framing (default) or new raw passthrough which caps read chunks at max_frame_size and skips latency telemetry (no send timestamps). Also adds disconnect_when_drained so a server can flush a final response before closing, with sends rejected while draining. The ByteQueue remainder path is generalized to optional headers to serve both framings. httparse (workspace dep) does head parsing; body handling stays in flux.
ltitanb
approved these changes
Aug 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
flux_network::http::HttpNetwork— a poll-driven HTTP/1.x layer on top ofTcpNetwork. One instance runs server and client in a single event loop: it can listen for inbound requests and maintain persistent outbound endpoints, delivering parsed requests/responses as borrowed events throughpoll_with.HTTP layer (
http.rs, new)listen+HttpEvent::Request; responses viarespond(token, status, headers, body), deferrable to a later poll (one pending request per connection, pipelined requests stay buffered behind it). HandlesExpect: 100-continue, HEAD semantics, HTTP/1.0/1.1 keep-alive vs close, and protocol errors (400/413/431/501) before user code sees anything.connect+request(token, method, path, headers, body)(one in flight per endpoint); responses supportContent-Length, chunked, and EOF-delimited bodies, with interim responses skipped.request.method/request.path).httparse(new workspace dep); body/chunked handling is in-crate.TcpNetwork changes (
network.rs)Framing: existingLengthPrefixed(default, unchanged) or newRawpassthrough. Raw groups cap read chunks atmax_frame_size, stamp events with local receive time, and skip latency telemetry (no wire timestamps).disconnect_when_drained(token): close after queued bytes flush (used forConnection: closeresponses); sends to a draining token are rejected.ByteQueueremainder path generalized to an optional header prefix to serve both framings.Testing
just fmt/just clippyclean (zero warnings).tests/http.rs), raw-framing suite (tests/tcp_network_raw.rs), and byte-queue unit tests.cargo test --workspace --all-features --lockedpasses. Note: in repeated local runs the pre-existingtcp_multi_client_backpressuretest flaked once under heavy machine load (fixed 5s deadline pushing 8MB through 1KB socket buffers); it exercisesTcpConnector(connector.rs/stream.rs), which this PR does not touch, and passes on retry.