Skip to content

fix(adapter-cloudflare): preserve user _headers rules that collide with autogenerated immutable headers - #16171

Closed
mcmxcdev wants to merge 3 commits into
sveltejs:mainfrom
mcmxcdev:fix-cloudflare-headers-collision
Closed

fix(adapter-cloudflare): preserve user _headers rules that collide with autogenerated immutable headers#16171
mcmxcdev wants to merge 3 commits into
sveltejs:mainfrom
mcmxcdev:fix-cloudflare-headers-collision

Conversation

@mcmxcdev

Copy link
Copy Markdown
Contributor

Problem

@sveltejs/adapter-cloudflare appends an autogenerated immutable-headers section to the user's _headers file. If the user already defined rules for /<app_dir>/* or /<app_dir>/immutable/*, the result contained two blocks for the same path. Cloudflare only applies the last matching rule per path (and combines colliding header values), so the user's headers were silently dropped — e.g. a custom Cross-Origin-Embedder-Policy on /_app/immutable/* never reached the response.

Fixes #15862

Solution

generate_headers now produces the entire _headers content:

  • Parse the user's _headers (parse_headers).
  • Strip any blocks colliding with the autogenerated paths (strip_headers_rules), leaving all other rules and comments untouched.
  • Re-emit a single merged block per autogenerated path with the user's headers folded in, so nothing is lost and there are never two blocks for the same path.
  • Negate the adapter's own headers first (! <name>) so they reliably override colliding user values instead of being comma-joined with them.

Non-colliding _headers files are unaffected aside from the autogenerated header lines now using tab indentation consistently.

Before submitting the PR, please make sure you have:

  • run the tests locally (pnpm -F @sveltejs/kit test:unit equivalent for the adapter — 20 passing)
  • added a changeset (patch)

🤖 Generated with Claude Code

…with autogenerated immutable headers

Cloudflare only applies the last matching rule for a given path and
combines colliding header values, so naively appending the autogenerated
immutable headers section silently dropped (or comma-joined) user-defined
rules for `/<app_dir>/*` and `/<app_dir>/immutable/*`.

Now we parse the user's `_headers`, strip any colliding blocks, and merge
their headers into a single autogenerated block per path. Adapter headers
are negated first (`! <name>`) so they reliably override colliding user
values instead of being combined.

Fixes sveltejs#15862

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Jun 25, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 1f249b3

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@sveltejs/adapter-cloudflare Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Comment thread packages/adapter-cloudflare/utils.js Outdated
`parse_headers` does not end a block on a blank line, but
`strip_headers_rules` reset `skip` on blank lines. A header line after a
blank inside a colliding block survived as an orphaned line and was also
duplicated in the merged autogenerated section. Stop resetting `skip` so
both functions treat blank lines consistently.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
teemingc added a commit that referenced this pull request Jun 27, 2026
closes #15862

A lighter alternative to #16171 ,
where we just add the rules under the URL if the URL already exists.

According to the Cloudflare docs, multiple headers will just be joined
with a comma
https://developers.cloudflare.com/workers/static-assets/headers/#attach-a-header
and we _shouldn't_ worry about someone also declaring new cache header
values for those URLs since they're framework related. The original
issue is mostly concerned about adding __new__ headers for CORS

---

### Please don't delete this checklist! Before submitting the PR, please
make sure you do the following:
- [ ] It's really useful if your PR references an issue where it is
discussed ahead of time. In many cases, features are absent for a
reason. For large changes, please create an RFC:
https://github.com/sveltejs/rfcs
- [x] This message body should clearly illustrate what problems it
solves.
- [x] Ideally, include a test that fails without this PR but passes with
it.

### Tests
- [ ] Run the tests with `pnpm test` and lint the project with `pnpm
lint` and `pnpm check`

### Changesets
- [x] If your PR makes a change that should be noted in one or more
packages' changelogs, generate a changeset by running `pnpm changeset`
and following the prompts. Changesets that add features should be
`minor` and those that fix bugs should be `patch`. Please prefix
changeset messages with `feat:`, `fix:`, or `chore:`.

### Edits

- [x] Please ensure that 'Allow edits from maintainers' is checked. PRs
without this option may be closed.
@teemingc

Copy link
Copy Markdown
Member

Closed in favour of #16183

@teemingc teemingc closed this Jun 27, 2026
LNSR added a commit to LNSR/wplokerbjm that referenced this pull request Jul 24, 2026
LNSR added a commit to LNSR/wplokerbjm that referenced this pull request Jul 24, 2026
LNSR added a commit to LNSR/wplokerbjm that referenced this pull request Jul 24, 2026
LNSR added a commit to LNSR/wplokerbjm that referenced this pull request Jul 24, 2026
LNSR added a commit to LNSR/wplokerbjm that referenced this pull request Jul 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

@sveltejs/adapter-cloudflare doesn't handle _headers collisions

2 participants