diff --git a/netlify.toml b/netlify.toml index 321f223..29bc444 100644 --- a/netlify.toml +++ b/netlify.toml @@ -30,6 +30,16 @@ to = "/.netlify/functions/qa-301" 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. +[[redirects]] + from = "/qa-403" + to = "/.netlify/functions/qa-403" + status = 200 + # Redirect all requests to /index.html for SPA routing [[redirects]] from = "/*" diff --git a/netlify/functions/qa-403.ts b/netlify/functions/qa-403.ts new file mode 100644 index 0000000..3ccfa41 --- /dev/null +++ b/netlify/functions/qa-403.ts @@ -0,0 +1,28 @@ +// 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" }, + }); +};