cfug / cfug/dio

[RFC] http2_adapter: expose response trailers (currently dropped)

Open
#2,602 1 comment 0 reactions 0 assignees View on GitHub

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 responseHeaders only racily — observable only if they happened to arrive before the response object was built (Headers.map returns 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-message are unreadable, and Trailers-Only error 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 HttpClientResponse does not expose trailers at all (no trailer API anywhere in sdk/lib/_http), so IOHttpClientAdapter has nothing to map today — worth noting for whichever option is chosen.
Proposal (options — all additive and non-breaking)
  1. Adapter-scoped, smallest surface: collect trailer headers in Http2Adapter and expose them via a documented extra key on ResponseBody (similar to the existing extraKeyHttpVersion). No core API change; weaker discoverability, http2-only.
  2. 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).
  3. Merge trailers into Response.headers after 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.