id: 31863f16-5f76-479b-be32-61b1107441a6 title: Cloudflare Pages clean-URL redirects break the one-shape canonical URL contract state: closed labels:
- area:render assignees: [] milestone: null created: 2026-10-27T18:40:05.827762324Z updated: 2026-10-27T19:53:10.473147998Z
Problem
Cloudflare Pages rewrites HTML routes to extensionless URLs, while hu13 build emits .html links and hu13 serve/nginx serve them directly. The dist/ is therefore not one canonical shape: every generated page link redirects on Pages.
Verified reproduction
Wrangler 4.154.0 wrangler pages dev dist:
GET /issues/index.html -> 308 Location: /issues/
GET /files/a.txt.html -> 308 Location: /files/a.txt
GET /raw/evil.html -> 308 Location: /raw/evil
GET /releases/v1.html -> 308 Location: /releases/v1
GET /releases/v1/evil.html -> 308 Location: /releases/v1/evil
GET /issues/, /files/a.txt, /raw/evil, and /releases/v1 then return 200. A _redirects rule with status 200 cannot override the clean-URL redirect (verified).
This also makes the artifact redirect path security-relevant: #106 is the actual active-content bug, and the redirect is what changes the final URL.
Impact
- Internal navigation and feed links take a 308 on Pages only.
- Raw HTML downloads redirect on Pages only.
- External canonical URLs (
/issues/index.html) are not the Pages canonical URL. - The one-shape requirement is not met even though pages remain reachable.
Fix options
Pick during convergence: emit extensionless canonical links and adapt serve/docs, or add a Pages-side function/worker that preserves .html, or explicitly declare Pages redirect behavior acceptable and document the canonical URL difference. Do not rely on _redirects to suppress the platform redirect.