Skip to content

feat(server): generate typed response headers - #115

Merged
lightsofapollo merged 1 commit into
gpu-cli:mainfrom
ToyVo:feat/server-response-headers
Nov 7, 2026
Merged

lightsofapollo merged 1 commit into
gpu-cli:mainfrom
ToyVo:feat/server-response-headers

Conversation

@ToyVo

@ToyVo ToyVo commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Implements #114

Response Objects with declared headers were silently dropped from generated Axum servers, leaving session-cookie flows (sign-in sets Set-Cookie, logout clears it) with nowhere to put headers in the typed response enums.

This generates a {Enum}{Variant}Headers struct per response that declares headers and threads it through as the variant's last field; into_response appends each value as its own header line, and an invalid value yields a 500. Semantics:

  • headers sorted by name; Content-Type excluded (the body owns it — the spec says a declared Content-Type response header is ignored)
  • String when required, Option otherwise, Vec for array schemas and always for Set-Cookie (RFC 9110 §5.3 forbids combining it)
  • header $refs to #/components/headers resolve; non-token header names fail generation
  • responses without declared headers generate exactly as before (additive, no wire change)

Also fixes string cookie parameters in generated clients (.as_ref() — they're impl AsRef, not Display, so any operation with one previously failed to compile).

Tests: new tests/server_response_headers_test.rs (3 tests) and tests/client_cookie_param_test.rs (1 test) — all pass. Validated end to end against a real auth API over the typed headers.

Generated compatibility

  • Generated model or method signatures: Response enums gain a {Enum}{Variant}Headers struct as the variant's last field, but only for responses that declare headers — everything else emits byte-identical output.
  • Query/path/header/body wire behavior: Request side untouched. Response wire is strictly additive: previously dropped headers are now emitted (one header line per value); an unencodable value yields a 500 where the header would previously have been silently missing.
  • Generated runtime dependencies or features: None added — emission uses only axum::http::{HeaderName, HeaderValue}, StatusCode, and std types already in the dependency set.
  • Configuration defaults or migrations: None — no new config knobs; existing specs need no changes.
  • Remaining unsupported OpenAPI shapes: Header values are strings on the wire (simple style); non-string header schemas still serialize through the existing scalar path. Out of scope: request-side header validation (unchanged) and trailers.

Validation

  • Added or updated a focused fixture and behavioral regression test.
  • Reviewed every changed snapshot; no unrelated churn is included.
  • cargo fmt --check
  • cargo clippy --all-features -- -D warnings
  • cargo test --all-features
  • Ran scripts/install-smoke.sh for packaging/dependency changes.
  • Ran a targeted or full scripts/spec-compile.sh for generator changes.
  • Updated README, rustdoc, or changelog for user-visible behavior.

Notes for reviewers

Smallest review path: tests/server_response_headers_test.rs first (pins the contract: collection sans Content-Type, invalid-name rejection, variants carry and emit headers incl. the Set-Cookie multi-line case), then response_headers_plan in src/server/codegen.rs, then the analysis.rs collector. Known judgment call: an unencodable header value returns 500 rather than failing generation — headers are runtime data, so generation can't validate values. Deliberately deferred: request-header validation and trailer support; also the client_cookie_param_test.rs fix (string cookies via .as_ref()) rides along as it's the same cookie story on the client side.

Response Objects with declared headers now produce a
{Enum}{Variant}Headers struct as the variant's last field and
into_response appends each value as its own header line.
Set-Cookie is always multi-value per RFC 9110 section 5.3;
a declared Content-Type stays ignored per the specification.
@vercel

vercel Bot commented Nov 6, 2026

Copy link
Copy Markdown

@ToyVo is attempting to deploy a commit to the lbl-rd Team on Vercel.

A member of the Team first needs to authorize it.

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.

2 participants