Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions docs/guide/edge/headers.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,18 @@ Define custom response headers in [`void.json`](../../reference/config) using th

## Scope

Header rules apply to **all responses** served through the dispatch worker, including static assets, SSR pages, and API routes. They do not apply to:
Header rules apply to **all responses** served through the dispatch worker, including static assets, SSR pages, API routes, and hashed asset responses (which browsers fetch over `GET` from the immutable edge cache). Serving headers on hashed assets is what lets a cross-origin-isolated app attach `Cross-Origin-Embedder-Policy` and `Cross-Origin-Resource-Policy` to its hashed worker and wasm files — without them, a module worker spawned from a `require-corp` document is blocked.

On hashed (content-addressed, immutable) assets, rules are **additive**. You can add headers such as COOP/COEP/CORP or other security headers, but the platform-managed caching, representation, and framing headers are preserved so an immutable asset cannot be mis-cached or corrupted: `Cache-Control`, `Content-Type`, `Content-Encoding`, `Content-Length`, `Content-Range`, `Accept-Ranges`, and `Transfer-Encoding` keep their platform values even if a broad rule tries to overwrite them. (This is the one case where a user `Cache-Control` does not override the default.)

Header rules do not apply to:

- Hashed asset cache hits (these use immutable caching set by the dispatch worker itself)
- ISR cache responses (these have their own cache-control headers)

### Blocked headers

Two headers can never be set through rules: `Set-Cookie` and `Clear-Site-Data`. On the shared `*.void.app` domain, `void.app` is the registrable domain, so a cookie operation from one project would reach every project's subdomain. Both are dropped from rule output to keep that tenant boundary intact.

## Framework `_headers` files

Meta-frameworks like SvelteKit, Nuxt, and Astro generate a `_headers` file with cache rules for their hashed asset directories. Void automatically parses this file during deploy and merges the rules into the deploy manifest.
Expand All @@ -74,6 +81,6 @@ No configuration is needed. If the framework generates a `_headers` file, it is

1. `void deploy` reads header rules from the framework `_headers` file (if present) and `routing.headers` in `void.json`, then includes them in the deploy manifest.
2. The platform stores the rules in the KV routing entry for your project.
3. The dispatch worker applies matching rules to matching responses before returning them. Cacheable responses are cached with the final headers.
3. The dispatch worker applies matching rules to matching responses before returning them. Most cacheable responses are cached with the final headers; hashed assets are the exception — their rules are applied on every serve (including cache hits), so a later header-rule change takes effect even when the content hash, and thus the cache entry, is unchanged.

Because rules are evaluated at the edge, there is no extra latency cost. Headers are applied inline before the response is returned and cached.