commit c839aa4c9b6cb8dd1435ac8e912b880d884c4326
parent 77c5280a426990c8d6929168902a519264621775
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date: Mon, 28 Sep 2026 13:34:45 -0400
homepage: _headers overrides detach the tree's Content-Type before setting their own
Pages applies EVERY matching `_headers` rule in file order and APPENDS a header
a later rule sets again (wrangler 4.88's attachHeaders, the Pages asset
server's code), so the plan's text served a directory page as
`text/plain; charset=utf-8, text/html; charset=utf-8` and a font as
`text/plain; charset=utf-8, font/ttf`. Each override now starts with
`! Content-Type`. A replica of wrangler's parse-and-attach over the two files
($T/r-m-headers-sim.mjs) gives single values for the index pages, the binaries
and the text files alike. PUBLISH.md says so.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Diffstat:
2 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/PUBLISH.md b/PUBLISH.md
@@ -181,7 +181,10 @@ tools.
`homepage/public/_headers` sets `/source/tree/*` to `text/plain; charset=utf-8` with
`nosniff` and `noindex`, then puts back `text/html` for the directory pages and the
real types of the few binaries (`.ttf`, `.m4a`, `.zip`, `.onnx`, `.svg` — the SVG
- under a `default-src 'none'` CSP). Only the ROOT `_headers` is read; the tree's own
+ under a `default-src 'none'` CSP). **Every matching rule applies, and a header a
+ later rule sets again is APPENDED** (`text/plain; charset=utf-8, text/html;
+ charset=utf-8`), so each of those overrides first detaches the tree's type with
+ `! Content-Type`. Only the ROOT `_headers` is read; the tree's own
copies are served as text. Locally, only `wrangler pages dev` honours `_headers` —
`next dev` and `serve` do not, and neither serves a directory's `index.html` at
`/<dir>/` the way Pages does.
diff --git a/homepage/public/_headers b/homepage/public/_headers
@@ -20,19 +20,30 @@
X-Content-Type-Options: nosniff
X-Robots-Tag: noindex
Cache-Control: public, max-age=300, must-revalidate
-# ...except the generated directory indexes and the binary files.
+# ...except the generated directory indexes and the binary files. Every rule
+# that matches applies, in file order, and a header a LATER rule sets again is
+# APPENDED to the earlier value ("text/plain; …, text/html; …" — wrangler's
+# attachHeaders, the Pages asset server's code). So each override first
+# detaches the tree's Content-Type with `! Content-Type`, then sets its own.
/source/tree/
+ ! Content-Type
Content-Type: text/html; charset=utf-8
/source/tree/*/
+ ! Content-Type
Content-Type: text/html; charset=utf-8
/source/tree/*.ttf
+ ! Content-Type
Content-Type: font/ttf
/source/tree/*.m4a
+ ! Content-Type
Content-Type: audio/mp4
/source/tree/*.zip
+ ! Content-Type
Content-Type: application/zip
/source/tree/*.onnx
+ ! Content-Type
Content-Type: application/octet-stream
/source/tree/*.svg
+ ! Content-Type
Content-Type: image/svg+xml
Content-Security-Policy: default-src 'none'; style-src 'unsafe-inline'