Fix 404 status code in dev server (#7711)
* chore: update tests * chore: update tests * fix(#7516): set response status to 404 when rendering 404 page * chore: add changeset * chore: update dev container test * refactor: improve status handling logic * chore: remove unused import
This commit is contained in:
parent
d401866f93
commit
72bbfac976
8 changed files with 45 additions and 9 deletions
5
.changeset/happy-carrots-lick.md
Normal file
5
.changeset/happy-carrots-lick.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Fix `status` code for custom `404` and `500` pages in the dev server
|
|
@ -25,7 +25,7 @@ type AsyncReturnType<T extends (...args: any) => Promise<any>> = T extends (
|
|||
? R
|
||||
: any;
|
||||
|
||||
interface MatchedRoute {
|
||||
export interface MatchedRoute {
|
||||
route: RouteData;
|
||||
filePath: URL;
|
||||
resolvedPathname: string;
|
||||
|
@ -125,12 +125,14 @@ type HandleRoute = {
|
|||
incomingRequest: http.IncomingMessage;
|
||||
incomingResponse: http.ServerResponse;
|
||||
manifest: SSRManifest;
|
||||
status?: number;
|
||||
};
|
||||
|
||||
export async function handleRoute({
|
||||
matchedRoute,
|
||||
url,
|
||||
pathname,
|
||||
status = getStatus(matchedRoute),
|
||||
body,
|
||||
origin,
|
||||
env,
|
||||
|
@ -198,6 +200,7 @@ export async function handleRoute({
|
|||
matchedRoute: fourOhFourRoute,
|
||||
url: new URL('/404', url),
|
||||
pathname: '/404',
|
||||
status: 404,
|
||||
body,
|
||||
origin,
|
||||
env,
|
||||
|
@ -236,6 +239,7 @@ export async function handleRoute({
|
|||
...options,
|
||||
matchedRoute: fourOhFourRoute,
|
||||
url: new URL(pathname, url),
|
||||
status: 404,
|
||||
body,
|
||||
origin,
|
||||
env,
|
||||
|
@ -246,6 +250,18 @@ export async function handleRoute({
|
|||
});
|
||||
}
|
||||
throwIfRedirectNotAllowed(result, config);
|
||||
return await writeSSRResult(request, result, incomingResponse);
|
||||
|
||||
let response = result;
|
||||
// Response.status is read-only, so a clone is required to override
|
||||
if (status && response.status !== status) {
|
||||
response = new Response(result.body, { ...result, status });
|
||||
}
|
||||
return await writeSSRResult(request, response, incomingResponse);
|
||||
}
|
||||
}
|
||||
|
||||
function getStatus(matchedRoute?: MatchedRoute): number | undefined {
|
||||
if (!matchedRoute) return 404;
|
||||
if (matchedRoute.route.route === '/404') return 404;
|
||||
if (matchedRoute.route.route === '/500') return 500;
|
||||
}
|
||||
|
|
|
@ -32,7 +32,10 @@ describe('Custom 404.html', () => {
|
|||
});
|
||||
|
||||
it('renders 404 for /a', async () => {
|
||||
const html = await fixture.fetch('/a').then((res) => res.text());
|
||||
const res = await fixture.fetch('/a');
|
||||
expect(res.status).to.equal(404);
|
||||
|
||||
const html = await res.text();
|
||||
$ = cheerio.load(html);
|
||||
|
||||
expect($('h1').text()).to.equal('Page not found');
|
||||
|
|
|
@ -32,7 +32,10 @@ describe('Custom 404 with injectRoute', () => {
|
|||
});
|
||||
|
||||
it('renders 404 for /a', async () => {
|
||||
const html = await fixture.fetch('/a').then((res) => res.text());
|
||||
const res = await fixture.fetch('/a');
|
||||
expect(res.status).to.equal(404);
|
||||
|
||||
const html = await res.text();
|
||||
$ = cheerio.load(html);
|
||||
|
||||
expect($('h1').text()).to.equal('Page not found');
|
||||
|
|
|
@ -31,7 +31,10 @@ describe('Custom 404 Markdown', () => {
|
|||
});
|
||||
|
||||
it('renders 404 for /abc', async () => {
|
||||
const html = await fixture.fetch('/a').then((res) => res.text());
|
||||
const res = await fixture.fetch('/a');
|
||||
expect(res.status).to.equal(404);
|
||||
|
||||
const html = await res.text();
|
||||
$ = cheerio.load(html);
|
||||
|
||||
expect($('h1').text()).to.equal('Page not found');
|
||||
|
|
|
@ -32,7 +32,10 @@ describe('Custom 404 server', () => {
|
|||
});
|
||||
|
||||
it('renders 404 for /a', async () => {
|
||||
const html = await fixture.fetch('/a').then((res) => res.text());
|
||||
const res = await fixture.fetch('/a');
|
||||
expect(res.status).to.equal(404);
|
||||
|
||||
const html = await res.text();
|
||||
$ = cheerio.load(html);
|
||||
|
||||
expect($('h1').text()).to.equal('Page not found');
|
||||
|
|
|
@ -32,7 +32,10 @@ describe('Custom 404', () => {
|
|||
});
|
||||
|
||||
it('renders 404 for /a', async () => {
|
||||
const html = await fixture.fetch('/a').then((res) => res.text());
|
||||
const res = await fixture.fetch('/a');
|
||||
expect(res.status).to.equal(404);
|
||||
|
||||
const html = await res.text();
|
||||
$ = cheerio.load(html);
|
||||
|
||||
expect($('h1').text()).to.equal('Page not found');
|
||||
|
|
|
@ -205,7 +205,7 @@ describe('dev container', () => {
|
|||
await r.done;
|
||||
const doc = await r.text();
|
||||
expect(doc).to.match(/<h1>Custom 404<\/h1>/);
|
||||
expect(r.res.statusCode).to.equal(200);
|
||||
expect(r.res.statusCode).to.equal(404);
|
||||
}
|
||||
{
|
||||
// A non-existent page also serves the custom 404 page.
|
||||
|
@ -214,7 +214,7 @@ describe('dev container', () => {
|
|||
await r.done;
|
||||
const doc = await r.text();
|
||||
expect(doc).to.match(/<h1>Custom 404<\/h1>/);
|
||||
expect(r.res.statusCode).to.equal(200);
|
||||
expect(r.res.statusCode).to.equal(404);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
Loading…
Reference in a new issue