fix(rerouting): check that the new route is different (#8648)
* fix(rerouting): check that the new route is different * add tests * changeset grammar
This commit is contained in:
parent
eada8ab8fa
commit
cfd895d877
22 changed files with 152 additions and 2 deletions
5
.changeset/wild-bees-sneeze.md
Normal file
5
.changeset/wild-bees-sneeze.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'astro': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fixed an issue where a response with status code 404 led to an endless loop of implicit rerouting in dev mode.
|
|
@ -220,6 +220,7 @@ export async function handleRoute({
|
||||||
let response = await pipeline.renderRoute(renderContext, mod);
|
let response = await pipeline.renderRoute(renderContext, mod);
|
||||||
if (response.status === 404 && has404Route(manifestData)) {
|
if (response.status === 404 && has404Route(manifestData)) {
|
||||||
const fourOhFourRoute = await matchRoute('/404', manifestData, pipeline);
|
const fourOhFourRoute = await matchRoute('/404', manifestData, pipeline);
|
||||||
|
if (fourOhFourRoute?.route !== options.route)
|
||||||
return handleRoute({
|
return handleRoute({
|
||||||
...options,
|
...options,
|
||||||
matchedRoute: fourOhFourRoute,
|
matchedRoute: fourOhFourRoute,
|
||||||
|
@ -342,6 +343,6 @@ function getStatus(matchedRoute?: MatchedRoute): 404 | 500 | undefined {
|
||||||
if (matchedRoute.route.route === '/500') return 500;
|
if (matchedRoute.route.route === '/500') return 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
function has404Route(manifest: ManifestData): RouteData | undefined {
|
function has404Route(manifest: ManifestData): boolean {
|
||||||
return manifest.routes.find((route) => route.route === '/404');
|
return manifest.routes.some((route) => route.route === '/404');
|
||||||
}
|
}
|
||||||
|
|
57
packages/astro/test/custom-404-implicit-rerouting.test.js
Normal file
57
packages/astro/test/custom-404-implicit-rerouting.test.js
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
import { expect } from 'chai';
|
||||||
|
import { loadFixture } from './test-utils.js';
|
||||||
|
|
||||||
|
for (const caseNumber of [ 1, 2, 3, 4 ]) {
|
||||||
|
describe(`Custom 404 with implicit rerouting - Case #${caseNumber}`, () => {
|
||||||
|
/** @type Awaited<ReturnType<typeof loadFixture>> */
|
||||||
|
let fixture;
|
||||||
|
/** @type Awaited<ReturnType<typeof fixture['startDevServer']>> */
|
||||||
|
let devServer
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
fixture = await loadFixture({
|
||||||
|
root: `./fixtures/custom-404-loop-case-${caseNumber}/`,
|
||||||
|
site: 'http://example.com'
|
||||||
|
});
|
||||||
|
|
||||||
|
devServer = await fixture.startDevServer();
|
||||||
|
});
|
||||||
|
|
||||||
|
// sanity check
|
||||||
|
it('dev server handles normal requests', async () => {
|
||||||
|
const resPromise = fixture.fetch('/');
|
||||||
|
const result = await withTimeout(resPromise, 1000);
|
||||||
|
expect(result).to.not.equal(timeout);
|
||||||
|
expect(result.status).to.equal(200);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('dev server stays responsive', async () => {
|
||||||
|
const resPromise = fixture.fetch('/alvsibdlvjks');
|
||||||
|
const result = await withTimeout(resPromise, 1000);
|
||||||
|
expect(result).to.not.equal(timeout);
|
||||||
|
expect(result.status).to.equal(404);
|
||||||
|
});
|
||||||
|
|
||||||
|
after(async () => {
|
||||||
|
await devServer.stop();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***** UTILITY FUNCTIONS *****/
|
||||||
|
|
||||||
|
const timeout = Symbol("timeout")
|
||||||
|
|
||||||
|
/** @template Res */
|
||||||
|
function withTimeout(
|
||||||
|
/** @type Promise<Res> */
|
||||||
|
responsePromise,
|
||||||
|
/** @type number */
|
||||||
|
timeLimit
|
||||||
|
) {
|
||||||
|
/** @type Promise<typeof timeout> */
|
||||||
|
const timeoutPromise = new Promise(resolve => setTimeout(() => resolve(timeout), timeLimit))
|
||||||
|
|
||||||
|
return Promise.race([ responsePromise, timeoutPromise ]);
|
||||||
|
}
|
1
packages/astro/test/fixtures/custom-404-loop-case-1/astro.config.mjs
vendored
Normal file
1
packages/astro/test/fixtures/custom-404-loop-case-1/astro.config.mjs
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export default {}
|
8
packages/astro/test/fixtures/custom-404-loop-case-1/package.json
vendored
Normal file
8
packages/astro/test/fixtures/custom-404-loop-case-1/package.json
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"name": "@test/custom-404-loop-case-1",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"private": true,
|
||||||
|
"dependencies": {
|
||||||
|
"astro": "workspace:*"
|
||||||
|
}
|
||||||
|
}
|
4
packages/astro/test/fixtures/custom-404-loop-case-1/src/pages/404.astro
vendored
Normal file
4
packages/astro/test/fixtures/custom-404-loop-case-1/src/pages/404.astro
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
Astro.response.status = 404
|
||||||
|
---
|
||||||
|
<p>four oh four route</p>
|
1
packages/astro/test/fixtures/custom-404-loop-case-1/src/pages/index.astro
vendored
Normal file
1
packages/astro/test/fixtures/custom-404-loop-case-1/src/pages/index.astro
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<p>all good here... or is it?</p>
|
1
packages/astro/test/fixtures/custom-404-loop-case-2/astro.config.mjs
vendored
Normal file
1
packages/astro/test/fixtures/custom-404-loop-case-2/astro.config.mjs
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export default {}
|
8
packages/astro/test/fixtures/custom-404-loop-case-2/package.json
vendored
Normal file
8
packages/astro/test/fixtures/custom-404-loop-case-2/package.json
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"name": "@test/custom-404-loop-case-2",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"private": true,
|
||||||
|
"dependencies": {
|
||||||
|
"astro": "workspace:*"
|
||||||
|
}
|
||||||
|
}
|
4
packages/astro/test/fixtures/custom-404-loop-case-2/src/pages/404.astro
vendored
Normal file
4
packages/astro/test/fixtures/custom-404-loop-case-2/src/pages/404.astro
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
return new Response(null, { status: 404 })
|
||||||
|
---
|
||||||
|
<p>four oh four route</p>
|
1
packages/astro/test/fixtures/custom-404-loop-case-2/src/pages/index.astro
vendored
Normal file
1
packages/astro/test/fixtures/custom-404-loop-case-2/src/pages/index.astro
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<p>all good here... or is it?</p>
|
1
packages/astro/test/fixtures/custom-404-loop-case-3/astro.config.mjs
vendored
Normal file
1
packages/astro/test/fixtures/custom-404-loop-case-3/astro.config.mjs
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export default {}
|
8
packages/astro/test/fixtures/custom-404-loop-case-3/package.json
vendored
Normal file
8
packages/astro/test/fixtures/custom-404-loop-case-3/package.json
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"name": "@test/custom-404-loop-case-3",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"private": true,
|
||||||
|
"dependencies": {
|
||||||
|
"astro": "workspace:*"
|
||||||
|
}
|
||||||
|
}
|
7
packages/astro/test/fixtures/custom-404-loop-case-3/src/middleware.js
vendored
Normal file
7
packages/astro/test/fixtures/custom-404-loop-case-3/src/middleware.js
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
export async function onRequest(ctx, next) {
|
||||||
|
if (ctx.url.pathname !== '/') {
|
||||||
|
const response = await next()
|
||||||
|
return new Response(response.body, { ...response, status: 404 })
|
||||||
|
}
|
||||||
|
return next();
|
||||||
|
}
|
1
packages/astro/test/fixtures/custom-404-loop-case-3/src/pages/404.astro
vendored
Normal file
1
packages/astro/test/fixtures/custom-404-loop-case-3/src/pages/404.astro
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<p>four oh four route</p>
|
1
packages/astro/test/fixtures/custom-404-loop-case-3/src/pages/index.astro
vendored
Normal file
1
packages/astro/test/fixtures/custom-404-loop-case-3/src/pages/index.astro
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<p>all good here... or is it?</p>
|
1
packages/astro/test/fixtures/custom-404-loop-case-4/astro.config.mjs
vendored
Normal file
1
packages/astro/test/fixtures/custom-404-loop-case-4/astro.config.mjs
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export default {}
|
8
packages/astro/test/fixtures/custom-404-loop-case-4/package.json
vendored
Normal file
8
packages/astro/test/fixtures/custom-404-loop-case-4/package.json
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"name": "@test/custom-404-loop-case-4",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"private": true,
|
||||||
|
"dependencies": {
|
||||||
|
"astro": "workspace:*"
|
||||||
|
}
|
||||||
|
}
|
6
packages/astro/test/fixtures/custom-404-loop-case-4/src/middleware.js
vendored
Normal file
6
packages/astro/test/fixtures/custom-404-loop-case-4/src/middleware.js
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
export function onRequest(ctx, next) {
|
||||||
|
if (ctx.url.pathname !== '/') {
|
||||||
|
return new Response(null, { status: 404 });
|
||||||
|
}
|
||||||
|
return next();
|
||||||
|
}
|
1
packages/astro/test/fixtures/custom-404-loop-case-4/src/pages/404.astro
vendored
Normal file
1
packages/astro/test/fixtures/custom-404-loop-case-4/src/pages/404.astro
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<p>four oh four route</p>
|
1
packages/astro/test/fixtures/custom-404-loop-case-4/src/pages/index.astro
vendored
Normal file
1
packages/astro/test/fixtures/custom-404-loop-case-4/src/pages/index.astro
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<p>all good here... or is it?</p>
|
|
@ -2561,6 +2561,30 @@ importers:
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../..
|
version: link:../../..
|
||||||
|
|
||||||
|
packages/astro/test/fixtures/custom-404-loop-case-1:
|
||||||
|
dependencies:
|
||||||
|
astro:
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../../..
|
||||||
|
|
||||||
|
packages/astro/test/fixtures/custom-404-loop-case-2:
|
||||||
|
dependencies:
|
||||||
|
astro:
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../../..
|
||||||
|
|
||||||
|
packages/astro/test/fixtures/custom-404-loop-case-3:
|
||||||
|
dependencies:
|
||||||
|
astro:
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../../..
|
||||||
|
|
||||||
|
packages/astro/test/fixtures/custom-404-loop-case-4:
|
||||||
|
dependencies:
|
||||||
|
astro:
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../../..
|
||||||
|
|
||||||
packages/astro/test/fixtures/custom-404-md:
|
packages/astro/test/fixtures/custom-404-md:
|
||||||
dependencies:
|
dependencies:
|
||||||
astro:
|
astro:
|
||||||
|
|
Loading…
Reference in a new issue