Skip to content

v0.5.0 — streaming request body

Choose a tag to compare

@EdmondDantes EdmondDantes released this 16 May 12:29
· 1149 commits to main since this release
21ec058

Highlights

Streaming request body (issue #26, PR #27)

New opt-in API for processing request bodies as they arrive, instead of buffering the whole Content-Length into req->body before dispatch.

New API

  • TrueAsync\HttpRequest::readBody(int $maxLen = 65536): ?string — pulls one parser-supplied chunk per call (16 KiB H2 DATA frame / 8 KiB H1 socket read), null at EOF. Parks the coroutine on a per-request trigger event when the queue is empty. Throws \Exception on stream error.
  • TrueAsync\HttpServerConfig::setBodyStreamingEnabled(bool): static / isBodyStreamingEnabled(): bool — server-wide flag, default false.

Impact (h2load, 50 concurrent 20 MiB POSTs, release PHP, WSL2):

peak RSS RPS
buffered 1170 MiB 36
streaming 197 MiB 100

≈ ×6 RSS reduction, ×2.7 throughput. Buffered handlers (no opt-in) keep byte-for-byte previous behaviour — A/B benchmarks on baseline H1/H2 and buffered upload show no regression beyond WSL2 noise.

Deferred to follow-up PRs (docs/PLAN_STREAMING_INGRESS.md):

  • Backpressure: llhttp_pause + NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE with deferred nghttp2_session_consume
  • HTTP/3 integration (ngtcp2_conn_extend_max_stream_offset)
  • readBodyChunks() — zero-copy scatter read
  • Mode trichotomy with LogicException (currently a single server-wide flag)
  • setMaxBodyQueueBytes() config setter (watermark hardcoded at 256 KiB)

See CHANGELOG.md for the full entry.