summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Emanuele Stoppa <my.burning@gmail.com> 2023-07-28 09:20:00 +0100
committerGravatar GitHub <noreply@github.com> 2023-07-28 09:20:00 +0100
commit2275c7d56b2b54e75ca1dbd1df5c7901cf358d52 (patch)
tree8414d95373f84d6c2084647bbfbe3e57350a7250
parent3b422272e642aa285ecfad3d2e9e2d8034eb2b7c (diff)
downloadastro-2275c7d56b2b54e75ca1dbd1df5c7901cf358d52.tar.gz
astro-2275c7d56b2b54e75ca1dbd1df5c7901cf358d52.tar.zst
astro-2275c7d56b2b54e75ca1dbd1df5c7901cf358d52.zip
fix: dev server should redirect when a page doesn't exist (#7841)
-rw-r--r--.changeset/plenty-bats-shake.md5
-rw-r--r--packages/astro/src/vite-plugin-astro-server/route.ts26
2 files changed, 24 insertions, 7 deletions
diff --git a/.changeset/plenty-bats-shake.md b/.changeset/plenty-bats-shake.md
new file mode 100644
index 000000000..8c561b770
--- /dev/null
+++ b/.changeset/plenty-bats-shake.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+Allow to return a redirect in dev mode when the original route is not present in the file system.
diff --git a/packages/astro/src/vite-plugin-astro-server/route.ts b/packages/astro/src/vite-plugin-astro-server/route.ts
index 119785a12..d08adab1a 100644
--- a/packages/astro/src/vite-plugin-astro-server/route.ts
+++ b/packages/astro/src/vite-plugin-astro-server/route.ts
@@ -31,6 +31,7 @@ import { preload } from './index.js';
import { getComponentMetadata } from './metadata.js';
import { handle404Response, writeSSRResult, writeWebResponse } from './response.js';
import { getScriptsForURL } from './scripts.js';
+import { isEndpointResult } from '../core/render/core.js';
const clientLocalsSymbol = Symbol.for('astro.locals');
@@ -140,7 +141,7 @@ type HandleRoute = {
incomingRequest: http.IncomingMessage;
incomingResponse: http.ServerResponse;
manifest: SSRManifest;
- status?: number;
+ status?: 404 | 500;
};
export async function handleRoute({
@@ -216,7 +217,7 @@ export async function handleRoute({
const onRequest = options.middleware?.onRequest as MiddlewareResponseHandler | undefined;
const result = await tryRenderRoute(route.type, renderContext, env, mod, onRequest);
- if (route.type === 'endpoint' && !(result instanceof Response)) {
+ if (isEndpointResult(result, route.type)) {
if (result.type === 'response') {
if (result.response.headers.get('X-Astro-Response') === 'Not-Found') {
const fourOhFourRoute = await matchRoute('/404', env, manifestData);
@@ -254,7 +255,7 @@ export async function handleRoute({
attachToResponse(response, result.cookies);
await writeWebResponse(incomingResponse, response);
}
- } else if (result instanceof Response) {
+ } else {
if (result.status === 404) {
const fourOhFourRoute = await matchRoute('/404', env, manifestData);
return handleRoute({
@@ -273,13 +274,24 @@ export async function handleRoute({
}
let response = result;
- // Response.status is read-only, so a clone is required to override
- if (status && response.status !== status) {
+
+ if (
+ // We are in a recursion, and it's possible that this function is called itself with a status code
+ // By default, the status code passed via parameters is computed by the matched route.
+ //
+ // By default, we should give priority to the status code passed, although it's possible that
+ // the `Response` emitted by the user is a redirect. If so, then return the returned response.
+ response.status < 400 &&
+ response.status >= 300
+ ) {
+ await writeSSRResult(request, response, incomingResponse);
+ return;
+ } else if (status && response.status !== status && (status === 404 || status === 500)) {
+ // Response.status is read-only, so a clone is required to override
response = new Response(result.body, { ...result, status });
}
await writeSSRResult(request, response, incomingResponse);
}
- // unreachable
}
interface GetScriptsAndStylesParams {
@@ -360,7 +372,7 @@ async function getScriptsAndStyles({ env, filePath }: GetScriptsAndStylesParams)
return { scripts, styles, links, metadata };
}
-function getStatus(matchedRoute?: MatchedRoute): number | undefined {
+function getStatus(matchedRoute?: MatchedRoute): 404 | 500 | undefined {
if (!matchedRoute) return 404;
if (matchedRoute.route.route === '/404') return 404;
if (matchedRoute.route.route === '/500') return 500;