@@ -31,6 +31,7 @@ import { preload } from './index.js';
3131import { getComponentMetadata } from './metadata.js' ;
3232import { handle404Response , writeSSRResult , writeWebResponse } from './response.js' ;
3333import { getScriptsForURL } from './scripts.js' ;
34+ import { isEndpointResult } from '../core/render/core.js' ;
3435
3536const clientLocalsSymbol = Symbol . for ( 'astro.locals' ) ;
3637
@@ -140,7 +141,7 @@ type HandleRoute = {
140141 incomingRequest : http . IncomingMessage ;
141142 incomingResponse : http . ServerResponse ;
142143 manifest : SSRManifest ;
143- status ?: number ;
144+ status ?: 404 | 500 ;
144145} ;
145146
146147export async function handleRoute ( {
@@ -216,7 +217,7 @@ export async function handleRoute({
216217 const onRequest = options . middleware ?. onRequest as MiddlewareResponseHandler | undefined ;
217218
218219 const result = await tryRenderRoute ( route . type , renderContext , env , mod , onRequest ) ;
219- if ( route . type === 'endpoint' && ! ( result instanceof Response ) ) {
220+ if ( isEndpointResult ( result , route . type ) ) {
220221 if ( result . type === 'response' ) {
221222 if ( result . response . headers . get ( 'X-Astro-Response' ) === 'Not-Found' ) {
222223 const fourOhFourRoute = await matchRoute ( '/404' , env , manifestData ) ;
@@ -254,7 +255,7 @@ export async function handleRoute({
254255 attachToResponse ( response , result . cookies ) ;
255256 await writeWebResponse ( incomingResponse , response ) ;
256257 }
257- } else if ( result instanceof Response ) {
258+ } else {
258259 if ( result . status === 404 ) {
259260 const fourOhFourRoute = await matchRoute ( '/404' , env , manifestData ) ;
260261 return handleRoute ( {
@@ -273,13 +274,24 @@ export async function handleRoute({
273274 }
274275
275276 let response = result ;
276- // Response.status is read-only, so a clone is required to override
277- if ( status && response . status !== status ) {
277+
278+ if (
279+ // We are in a recursion, and it's possible that this function is called itself with a status code
280+ // By default, the status code passed via parameters is computed by the matched route.
281+ //
282+ // By default, we should give priority to the status code passed, although it's possible that
283+ // the `Response` emitted by the user is a redirect. If so, then return the returned response.
284+ response . status < 400 &&
285+ response . status >= 300
286+ ) {
287+ await writeSSRResult ( request , response , incomingResponse ) ;
288+ return ;
289+ } else if ( status && response . status !== status && ( status === 404 || status === 500 ) ) {
290+ // Response.status is read-only, so a clone is required to override
278291 response = new Response ( result . body , { ...result , status } ) ;
279292 }
280293 await writeSSRResult ( request , response , incomingResponse ) ;
281294 }
282- // unreachable
283295}
284296
285297interface GetScriptsAndStylesParams {
@@ -360,7 +372,7 @@ async function getScriptsAndStyles({ env, filePath }: GetScriptsAndStylesParams)
360372 return { scripts, styles, links, metadata } ;
361373}
362374
363- function getStatus ( matchedRoute ?: MatchedRoute ) : number | undefined {
375+ function getStatus ( matchedRoute ?: MatchedRoute ) : 404 | 500 | undefined {
364376 if ( ! matchedRoute ) return 404 ;
365377 if ( matchedRoute . route . route === '/404' ) return 404 ;
366378 if ( matchedRoute . route . route === '/500' ) return 500 ;
0 commit comments