diff --git a/netlify.toml b/netlify.toml index 6665c11..f2705b6 100644 --- a/netlify.toml +++ b/netlify.toml @@ -20,24 +20,24 @@ to = "/.netlify/functions/qa-status" status = 200 -# QA-only: expose the qa-301 function at the clean path /qa-301. Same -# rewrite-proxy mechanism as /qa-status above (status = 200 is the -# rewrite TYPE, not a forced response code) — it preserves the -# function's actual 301 status code AND its Location header. Must -# remain BEFORE the SPA catch-all below. +# QA-only: route /qa-301 to the parameterized qa-code function, which +# emits a real HTTP 301 + Location header for this path. Same +# rewrite-proxy mechanism as /qa-status above — status = 200 is the +# rewrite TYPE, not a forced response code. Must remain BEFORE the +# SPA catch-all below. [[redirects]] from = "/qa-301" - to = "/.netlify/functions/qa-301" + to = "/.netlify/functions/qa-code" status = 200 -# QA-only: expose the qa-403 function at the clean path /qa-403. Same -# rewrite-proxy mechanism as the QA endpoints above (status = 200 is -# the rewrite TYPE, not a forced response code) — it preserves the -# function's actual 403 status and its text/html Content-Type. Must -# remain BEFORE the SPA catch-all below. +# QA-only: route /qa-403 to the parameterized qa-code function, which +# emits a real HTTP 403 + text/html body for this path. Same +# rewrite-proxy mechanism as the QA endpoints above — status = 200 is +# the rewrite TYPE, not a forced response code. Must remain BEFORE the +# SPA catch-all below. [[redirects]] from = "/qa-403" - to = "/.netlify/functions/qa-403" + to = "/.netlify/functions/qa-code" status = 200 # QA-only: additional fixed-status endpoints handled by a single diff --git a/netlify/functions/qa-301.ts b/netlify/functions/qa-301.ts deleted file mode 100644 index dc85a9b..0000000 --- a/netlify/functions/qa-301.ts +++ /dev/null @@ -1,17 +0,0 @@ -// QA-only Netlify Function that always returns a real HTTP 301 redirect -// to the site homepage. Used to test Prerender's handling of 3xx -// responses on a clean, page-looking URL. Reached publicly via /qa-301 -// (see redirect in netlify.toml). -// -// The 301 status code and Location header are set by THIS function and -// passed through unchanged by Netlify's status=200 rewrite proxy — the -// client sees the 301 + Location, Netlify does not auto-follow it. - -export default async (_req: Request): Promise => { - return new Response(null, { - status: 301, - headers: { - Location: "https://weirdanimals.life/", - }, - }); -}; diff --git a/netlify/functions/qa-403.ts b/netlify/functions/qa-403.ts deleted file mode 100644 index 3ccfa41..0000000 --- a/netlify/functions/qa-403.ts +++ /dev/null @@ -1,28 +0,0 @@ -// QA-only Netlify Function that always returns a real HTTP 403 -// Forbidden with a minimal HTML body. Used to test Prerender's -// handling of 4xx responses on a clean, page-looking URL. Reached -// publicly via /qa-403 (see redirect in netlify.toml). -// -// The 403 status code and Content-Type are set by THIS function and -// passed through unchanged by Netlify's status=200 rewrite proxy — -// the client sees a real 403, not a 200 carrying error text. - -export default async (_req: Request): Promise => { - const html = ` - - - - - 403 - QA - - -

Forbidden

- - -`; - - return new Response(html, { - status: 403, - headers: { "Content-Type": "text/html; charset=utf-8" }, - }); -}; diff --git a/netlify/functions/qa-code.ts b/netlify/functions/qa-code.ts index d7f2792..350c9ea 100644 --- a/netlify/functions/qa-code.ts +++ b/netlify/functions/qa-code.ts @@ -1,15 +1,19 @@ // QA-only Netlify Function used to emit a fixed HTTP status code based on // the public path the request came in on. One function, many rewrites in -// netlify.toml (one per code: /qa-302, /qa-303, /qa-307, /qa-308, /qa-401, -// /qa-404, /qa-429). Used to test how Prerender handles each status on a -// clean, page-looking URL. +// netlify.toml (one per code: /qa-301, /qa-302, /qa-303, /qa-307, /qa-308, +// /qa-401, /qa-403, /qa-404, /qa-429). Used to test how Prerender handles +// each status on a clean, page-looking URL. +// +// Note: /qa-status (200/500 via QA_FORCE_500 env toggle) is intentionally +// kept as its own function — it carries runtime configuration that does +// not fit a generic fixed-status dispatcher. // // How status preservation works: // - The status code AND headers (Location / Content-Type) are set by THIS // function and passed through unchanged by Netlify's status=200 rewrite -// proxy in netlify.toml. The client sees a real 302/303/307/308/401/ -// 404/429 — not a 200 with error text, and Netlify does not auto-follow -// the 3xx redirects server-side. +// proxy in netlify.toml. The client sees a real 301/302/303/307/308/ +// 401/403/404/429 — not a 200 with error text, and Netlify does not +// auto-follow the 3xx redirects server-side. // // How the path is read: // - In Netlify Functions v2, req.url reflects the URL the client actually @@ -36,11 +40,13 @@ type CodeConfig = RedirectConfig | HtmlConfig; const REDIRECT_LOCATION = "https://weirdanimals.life/"; const CODES: Record = { + "301": { kind: "redirect", status: 301 }, "302": { kind: "redirect", status: 302 }, "303": { kind: "redirect", status: 303 }, "307": { kind: "redirect", status: 307 }, "308": { kind: "redirect", status: 308 }, "401": { kind: "html", status: 401, title: "401 - QA", heading: "Unauthorized" }, + "403": { kind: "html", status: 403, title: "403 - QA", heading: "Forbidden" }, "404": { kind: "html", status: 404, title: "404 - QA", heading: "Not Found" }, "429": { kind: "html", status: 429, title: "429 - QA", heading: "Too Many Requests" }, };