Files
Flash5/flash/docs/core/TRAILERS-AND-STREAMING.md
T
Zakaria El Orche a0dda8e47a refactor(core): remove out-of-scope HTTP/2 client/proxy, reorganize docs, refresh README
HttpProxy and Http2Client (719 LOC) shipped a reverse-proxy adapter and outbound HTTP/2
client from flash core with zero callers anywhere in the server itself — only each
other and their own tests. An HTTP/1.1+2 server framework has no business bundling an
outbound client; that capability belongs in its own flash-extensions/flash-ext-*
module if/when it's needed. Removed, along with the now-dead src/bench load driver
that depended on Http2Client (no replacement client written here — flagged as
follow-up work, not silently dropped).

docs/http2/ had accumulated core, cross-protocol documentation alongside genuine
HTTP/2-protocol internals: HTTP1-HARDENING, TRANSPORT, MESSAGE-MODEL,
TRAILERS-AND-STREAMING and BYTES all describe machinery HTTP/1.1 and HTTP/2 share, not
HTTP/2 specifically. Moved to a new docs/core/, leaving docs/http2/ to the protocol
layers, wire internals and operational docs that are actually HTTP/2-specific.
CLEARTEXT-AND-PROXY.md renamed to CLEARTEXT.md and its now-removed upstream-client
section cut, matching the source removal above.

README.md: removed the "HTTP/2 upstream proxy" section (documented the deleted
HttpProxy/Http2Client), the flash-bench module row and build command (not a module
that exists in this repo), and fixed every doc link to the new docs/core/ paths.
Added the new FlashConfiguration.maxConnections field to the configuration reference.

src/bench/ (a load-test harness distinct from the JMH suite, not wired into any Maven
profile or CI) is committed here for the first time.
2026-08-14 18:13:03 +00:00

1.9 KiB

Trailers and streaming

Flash exposes the same request and response model on HTTP/1.1 and HTTP/2. Request trailers are available through Request.trailers() after the body has reached EOF. Calling it earlier throws IllegalStateException; this prevents handlers from observing an incomplete trailer section. HTTP/1.1 reads trailers from the final chunk, while HTTP/2 decodes the trailing HEADERS block in the connection's existing HPACK context.

Response trailers are added with Response.trailer(name, value) or a PreEncodedHeader. HTTP/1.1 uses chunked framing and writes the fields after the zero chunk. HTTP/2 writes a trailing HEADERS block with END_STREAM; the final DATA frame deliberately does not carry END_STREAM.

Response.streaming(producer) is the push alternative to stream(InputStream, length) and chunked(InputStream). Its ResponseStream is a bounded blocking bridge. A producer runs on a virtual thread and blocks when the protocol writer or the HTTP/2 flow-control windows cannot make progress. This keeps backpressure explicit without callbacks or reactive types:

return response.type("application/grpc").streaming(stream -> {
  try {
    for (byte[] message : messages) stream.write(message, 0, message.length);
    stream.trailer("grpc-status", "0");
  } catch (IOException failure) {
    throw new UncheckedIOException(failure);
  }
});

The transport supports the primitives required by gRPC, but the core does not provide protobuf codecs, generated stubs, service descriptors, or a gRPC service API. Those belong in a future flash-ext-grpc module. GrpcInteropTest verifies the boundary with the external grpcurl client and a hand-written wire-format handler.

CONNECT requests follow RFC 9113 request pseudo-header rules: :authority is required and :scheme/:path are forbidden. Their DATA remains subject to the ordinary request limits, timeouts and two-level flow control.