[RFC] http2_adapter: expose response trailers (currently dropped)
Nobody has claimed this yet.
- Dominant language
- Dart
- Stars
- 12.8k
- Forks
- 1.6k
- PR merge metrics
- No merged PRs in 30d
Description
Package
http2_adapter
Motivation
What cannot be done today: read HTTP/2 response trailers. The adapter discards them.
In HTTP/2, a server may send a trailer section as a final HEADERS frame (no :status, END_STREAM set) after the response body (RFC 9113 §8.4, §8.8.5). Today Http2Adapter._fetch parses these frames and discards them:
- Before #2601 (the fix for #2600), trailers were merged into
responseHeadersonly racily — observable only if they happened to arrive before the response object was built (Headers.mapreturns the live internal map), so it was never a usable API. - #2601 makes the drop deterministic.
Who needs this, and in which real-world scenario:
- gRPC over HTTP/2 through dio. The gRPC/HTTP2 spec requires the call result to travel in trailers:
Response → (Response-Headers *Length-Prefixed-Message Trailers) / Trailers-Only, and "Status must be sent in Trailers even if the status code is OK" (grpc/grpc,doc/PROTOCOL-HTTP2.md). Without trailer access,grpc-status/grpc-messageare unreadable, andTrailers-Onlyerror responses look like empty 200s. - Integrity checksums in trailers (payload checksums sent after the body) cannot be verified.
- The same gap exists on the HTTP/1.1 side (
IOHttpClientAdapter), but HTTP/2 is where trailers are most common.
Why this belongs in dio rather than an interceptor / transformer / separate package: trailers exist only inside the adapter — they are dropped before the response pipeline sees anything, so no interceptor or transformer can recover them. Capture must happen in the adapter, and surfacing them usefully needs a small dio-side API.
Prior art
- Go
net/http:Response.Trailer(src/net/http/response.go) — a trailer map populated after the body is consumed. - dart:io
HttpClientResponsedoes not expose trailers at all (no trailer API anywhere insdk/lib/_http), soIOHttpClientAdapterhas nothing to map today — worth noting for whichever option is chosen.
Proposal (options — all additive and non-breaking)
- Adapter-scoped, smallest surface: collect trailer headers in
Http2Adapterand expose them via a documentedextrakey onResponseBody(similar to the existingextraKeyHttpVersion). No core API change; weaker discoverability, http2-only. - Core API:
ResponseBody.trailers+Response.trailers(populated once the body stream completes), with each adapter mapping what its platform provides. Most usable and cross-adapter; requires core changes and per-adapter decisions (dart:io currently offers no API to map; browsers cannot provide trailers). - Merge trailers into
Response.headersafter body completion — not recommended: conflates the header section with trailers and breaks the assumption that headers are settled once the response headers arrive.
My inclination would be (2) for the long-term shape, or (1) as an incremental first step if maintainers prefer to keep the core surface untouched.
Compatibility
Any option is additive; no existing signature or default behavior changes. Interim (1xx) headers remain excluded regardless (see #2600 / #2601).
Issue body drafted with AI assistance (GLM), reviewed and submitted by a human.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading Http2Adapter._fetch and the ResponseBody and Response definitions to understand where response trailers are currently discarded and how response metadata is exposed. Resolve with maintainers whether to implement the adapter-scoped extra key or the core trailers API, then verify that HTTP/2 trailers remain available after body completion without merging them into response headers.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- dart
- Domain
- backend-api-design, networking
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 30/100