Skip to content

fix(cors): preserve CORS headers on error responses#1352

Merged
pi0 merged 4 commits into
mainfrom
feat/error-headers
Mar 19, 2026
Merged

fix(cors): preserve CORS headers on error responses#1352
pi0 merged 4 commits into
mainfrom
feat/error-headers

Conversation

@pi0
Copy link
Copy Markdown
Member

@pi0 pi0 commented Mar 19, 2026

Summary

When an HTTPError is thrown after CORS headers have been set via handleCors(), the CORS headers were dropped from the error response. This caused browsers to hide error details from the client, since the response lacked the required access-control-allow-origin header.

Root cause: event.res.headers (prepared headers) are only merged into successful responses. When an error is thrown, the error response is built separately and these headers are discarded.

Fix: Use event.res.errHeaders — a dedicated header store that persists into error responses:

  • CORS utils (appendCorsHeaders, appendCorsPreflightHeaders) now set headers on both event.res.headers and event.res.errHeaders
  • errorResponse() in response.ts merges errHeaders into the error response
  • Updated docs to explain the distinction between event.res.headers (discarded on error) and event.res.errHeaders (preserved on error)

Closes #1301

Test plan

  • Added unit test: preserves CORS headers on HTTPError responses
  • All existing CORS tests pass
  • Bundle size threshold updated

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • CORS headers are now automatically preserved in HTTP error responses, ensuring proper cross-origin compatibility when errors occur.
  • Documentation

    • Added comprehensive guidance on including custom headers in HTTP error responses and managing response headers during error scenarios.
  • Tests

    • Added test coverage for CORS header behavior in error handling.

set CORS headers on both `event.res.headers` and `event.res.errHeaders`
so they are merged into error responses when an HTTPError is thrown.

closes #1301
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 19, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 015dc162-923c-4318-8ce4-7251bdeb7340

📥 Commits

Reviewing files that changed from the base of the PR and between e5c660d and b4eacb1.

📒 Files selected for processing (7)
  • docs/1.guide/1.basics/5.response.md
  • docs/1.guide/1.basics/6.error.md
  • src/event.ts
  • src/response.ts
  • src/utils/cors.ts
  • test/bench/bundle.test.ts
  • test/unit/cors.test.ts

📝 Walkthrough

Walkthrough

Adds per-event error-response header storage and merges those headers into error responses; updates CORS helpers to write into both normal and error headers; documents the new recommended patterns; and adds a unit test plus a minor bundle-size test threshold change.

Changes

Cohort / File(s) Summary
Documentation Updates
docs/1.guide/1.basics/5.response.md, docs/1.guide/1.basics/6.error.md
Clarifies recommended pattern for setting headers on errors (new HTTPError({ headers })) and documents event.res.errHeaders as the fallback for headers prepared before an error is known; describes header precedence and helper behavior.
Event API
src/event.ts
Adds exported symbol kEventResErrHeaders and H3EventResponse.get errHeaders(): Headers — lazy per-event storage for error-specific headers separate from normal response headers.
Response Handling
src/response.ts
prepareResponse now reads event errHeaders when producing an error response; errorResponse accepts an optional errHeaders?: Headers and merges them into the final error response headers.
CORS Utilities
src/utils/cors.ts
appendCorsPreflightHeaders and appendCorsHeaders now append access-control-* entries to both event.res.headers and event.res.errHeaders.
Tests
test/unit/cors.test.ts, test/bench/bundle.test.ts
Adds unit test verifying CORS headers are preserved on HTTPError responses; relaxes a bundle-size assertion from 6000 to 6100 bytes.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I stash my headers nice and neat,
For errors that may hop and greet,
Cors lights copied, none shall flee,
ErrHeaders keep them safe for me —
A little nibble, then complete. 🥕✨

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/error-headers
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Mar 19, 2026

Open in StackBlitz

npm i https://pkg.pr.new/h3@1352

commit: b4eacb1

pi0 and others added 3 commits March 19, 2026 20:03
mention that prepared headers are discarded on errors and that
`event.res.errHeaders` should be used for headers that need to
persist on error responses (e.g., CORS headers).
clarify that explicit error headers via `HTTPError` constructor is the
preferred approach, and `event.res.errHeaders` is a last resort for
implicit headers like CORS.
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.

cors headers dropped on HTTPError (v2)

1 participant