Skip to content

Fix late trailers on streaming HTTP responses - #1553

Merged
jlouvel merged 1 commit into
3.0from
feat/rpc-r1-late-http2-trailers
Oct 20, 2026
Merged

jlouvel merged 1 commit into
3.0from
feat/rpc-r1-late-http2-trailers

Conversation

@jlouvel

@jlouvel jlouvel commented Oct 20, 2026

Copy link
Copy Markdown
Collaborator

Summary

Allow HTTP/2 and HTTP/3 streaming responses to publish trailers after the response head and body have started streaming.

The connector now keeps trailer emission enabled for stream-based responses that can carry a body, even when the trailer collection is empty when response headers are written. HTTP/1.1 continues to require trailer names before the response head, and bodyless responses remain unchanged.

Validation

  • mvnw -q -pl org.restlet '-Dtest=HttpTrailersTestCase,Http2TrailerHeadersTestCase' test
  • mvnw -q -pl org.restlet -Dtest=Http3TestCase#getAndPutOverHttp3 test
  • mvnw -q -pl org.restlet -Dtest=Http3TestCase#exchangesTrailersAddedAfterTheFirstBodyFlushOverHttp3 test
  • mvnw -q -pl org.restlet spotless:check

The regression tests cover late trailers after a body flush on both HTTP/2 and HTTP/3, plus existing HTTP/1.1/HTTP/2 trailer behavior.

Signed-off-by: Jerome Louvel <[email protected]>
Co-authored-by: Copilot <[email protected]>
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
D Maintainability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@jlouvel
jlouvel merged commit 55d38a2 into 3.0 Oct 20, 2026
1 of 3 checks passed
@jlouvel
jlouvel deleted the feat/rpc-r1-late-http2-trailers branch October 20, 2026 21:12
jlouvel added a commit that referenced this pull request Oct 20, 2026
Address the failures detected on PR #1553 and on the 3.0 branch:

- ChannelOutputStream: writes from a call thread only update the channel
  writability once the event loop processes them, so a fast producer
  could queue a whole response body and never notice that the stream was
  reset (flaky Http2CancellationTestCase). Bound the bytes in flight to
  the channel high water mark and fail on the first failed write.
- NettyServerHandler: end the request body at once for HTTP/1.1 requests
  without a body. The call could otherwise complete before the empty last
  content was delivered and close a connection announced as kept alive
  (flaky RedirectTestCase.stopsAfterMaxRedirects).
- NettyServerCall: split writeHead to fix the SonarCloud cognitive
  complexity issue (java:S3776), without behavior change.

Co-authored-by: Copilot <[email protected]>
jlouvel added a commit that referenced this pull request Oct 21, 2026
Address the failures detected on PR #1553 and on the 3.0 branch:

- ChannelOutputStream: writes from a call thread only update the channel
  writability once the event loop processes them, so a fast producer
  could queue a whole response body and never notice that the stream was
  reset (flaky Http2CancellationTestCase). Bound the bytes in flight to
  the channel high water mark and fail on the first failed write.
- NettyServerHandler: end the request body at once for HTTP/1.1 requests
  without a body. The call could otherwise complete before the empty last
  content was delivered and close a connection announced as kept alive
  (flaky RedirectTestCase.stopsAfterMaxRedirects).
- NettyServerCall: split writeHead to fix the SonarCloud cognitive
  complexity issue (java:S3776), without behavior change.

Co-authored-by: Copilot <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant