Repository navigation
Backend: streaming request and response bodies, spooled uploads, HttpProxy - #6095
Conversation
Large binary uploads spool to an unlinked file on HTTP/1.1 and HTTP/2 alike; Web.open streams outbound requests both ways; HttpProxy forwards with hop-by-hop stripping, a destination allow-list and cancellation both ways. HTTP/2 used to serve an upload truncated at the body limit: frames in flight after the refusing chunk still completed the request. Such a stream is now answered 413, as HTTP/1.1 answers it. Fixes #5994 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Developer Guide build artifacts are available for download from this workflow run:
Developer Guide quality checks: |
Cloudflare Preview
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
✅ Continuous Quality ReportTest & Coverage
Static Analysis
Generated automatically by the PR CI workflow. |
|
Compared 214 screenshots: 214 matched. |
|
Compared 178 screenshots: 178 matched. Native Android coverage
✅ Native Android screenshot tests passed. Native Android coverage
Benchmark ResultsDetailed Performance Metrics
|
|
Compared 193 screenshots: 193 matched. Benchmark ResultsDetailed Performance Metrics
|
|
Compared 193 screenshots: 193 matched. Benchmark ResultsDetailed Performance Metrics
ParparVM vs HotSpot (JDK 25): Windows x64Runner CPU: Intel64 Family 6 Model 207 Stepping 2, GenuineIntel (baseline 1 improvement past the baseline (not a failure; rebaseline to lock it in):
Ratios are ParparVM / JDK 25: below 1.00x ParparVM is faster (time) or smaller (RAM). Median of 5 interleaved, paired rounds; every run's output was verified. A ratio more than 20% (time) / 25% (RAM) above its baseline in
A change that moves performance ON PURPOSE records the new baseline in Result: no regression (improved past the baseline: consider rebaselining) |
✅ ByteCodeTranslator Quality ReportTest & Coverage
Benchmark Results
Static Analysis
Generated automatically by the PR CI workflow. |
|
Compared 193 screenshots: 193 matched. Benchmark ResultsDetailed Performance Metrics
ParparVM vs HotSpot (JDK 25): Windows arm64Runner CPU: ARMv8 (64-bit) Family 8 Model D49 Revision 0, MICROSOFT CORPORATION (baseline Ratios are ParparVM / JDK 25: below 1.00x ParparVM is faster (time) or smaller (RAM). Median of 5 interleaved, paired rounds; every run's output was verified. A ratio more than 20% (time) / 25% (RAM) above its baseline in
Result: no regression |
|
Compared 193 screenshots: 193 matched. ParparVM vs HotSpot (JDK 25): Linux x64Runner CPU: AMD EPYC 7763 64-Core Processor (baseline Ratios are ParparVM / JDK 25: below 1.00x ParparVM is faster (time) or smaller (RAM). Median of 5 interleaved, paired rounds; every run's output was verified. A ratio more than 20% (time) / 25% (RAM) above its baseline in
Result: no regression |
|
Compared 193 screenshots: 193 matched. ParparVM vs HotSpot (JDK 25): Linux arm64Runner CPU: Neoverse-N2 (baseline Ratios are ParparVM / JDK 25: below 1.00x ParparVM is faster (time) or smaller (RAM). Median of 5 interleaved, paired rounds; every run's output was verified. A ratio more than 20% (time) / 25% (RAM) above its baseline in
Result: no regression |
|
Compared 179 screenshots: 179 matched. Benchmark Results
Detailed Performance Metrics
ParparVM vs HotSpot (JDK 25): macOS arm64Runner CPU: Apple M1 (Virtual) (baseline Ratios are ParparVM / JDK 25: below 1.00x ParparVM is faster (time) or smaller (RAM). Median of 5 interleaved, paired rounds; every run's output was verified. A ratio more than 20% (time) / 25% (RAM) above its baseline in
Result: no regression |
|
Compared 176 screenshots: 176 matched. Benchmark Results
Build and Run Timing
Detailed Performance Metrics
|
|
Compared 176 screenshots: 176 matched. Benchmark Results
Build and Run Timing
Detailed Performance Metrics
|
|
Compared 236 screenshots: 236 matched. |
|
Compared 175 screenshots: 175 matched. Benchmark Results
Detailed Performance Metrics
|
|
Compared 171 screenshots: 171 matched. |
Fixes #5994.
What it adds
CN1_HTTP_SPOOL_THRESHOLD_KB(1024) is written to an unlinked temporary file as it arrives, on HTTP/1.1 and HTTP/2 alike.Request.getBodyStream()andgetBodyLength()read it, and multipart parts are slices of the spool (Part.getInputStream(),getLength()).CN1_HTTP_MAX_SPOOLED_BODY_MBraises the limit for such bodies.CN1_HTTP_SPOOL_DIRpicks the directory.Web.open/WebClient.openreturn aWeb.Exchange: the request body is written as it is produced, the response is read as it arrives, and each direction has a fixed window.close()before the end cancels the exchange. The packaged binary uses curl multi with pause/resume; the JVM twin uses HttpURLConnection.HttpServer.Response.streamis chunked on HTTP/1.1 and DATA frames on HTTP/2. ABodyWriterthat also implementsCloseableis closed when the server never runs it: a HEAD, a bodiless status, an HTTP/2 stream it could not open, or a head write that failed.HttpProxy:Connectionfield names, in both directions.X-Forwarded-*.allowHost, overhttpandhttps.setFollowRedirects(n)follows them only for a request without a body, and dropsAuthorizationandCookieon a hop to another host.Content-Encoding.Content-Length.Found along the way and fixed here
RST_STREAM(NO_ERROR)once the 413 is on the wire, because nghttp2 sends a queued reset ahead of queued HEADERS). That matches HTTP/1.1.Verification
HttpStreamingTest(12 tests) andHttpBodiesTest(30 tests) pass on the JVM runtime.BackendHttpIntegrationTest#http2BodyPastTheLimitIsAnswered413runs against the translated native server, together with the existing h2 body tests.vm/backend/demo/streamcheckran on the JVM and as a native binary: upload, download, cancellation, proxied body, headers, destinations and redirects (7/7 on both).--http1.1vs--http2-prior-knowledge, at the default limit and withCN1_HTTP_MAX_SPOOLED_BODY_MB=20, gave the same results on both protocols:check-native-signatures.sh(369 backend natives resolve).docs/demos/backend/.../Streaming.java), andvalidate-guide-snippets.pypasses.🤖 Generated with Claude Code