@@ -225,43 +225,73 @@ async function processRequest(
225225 // https://github.com/dougmoscrop/serverless-http/issues/227
226226 delete req . body ;
227227
228+ // Here we try to apply as much request metadata as possible
229+ // We apply every metadata from `resolve-routes` https://github.com/vercel/next.js/blob/916f105b97211de50f8580f0b39c9e7c60de4886/packages/next/src/server/lib/router-utils/resolve-routes.ts
230+ // and `router-server` https://github.com/vercel/next.js/blob/916f105b97211de50f8580f0b39c9e7c60de4886/packages/next/src/server/lib/router-server.ts
231+ const initialURL = new URL ( routingResult . initialURL ) ;
232+ let invokeStatus : number | undefined ;
233+ if ( routingResult . internalEvent . rawPath === "/500" ) {
234+ invokeStatus = 500 ;
235+ } else if ( routingResult . internalEvent . rawPath === "/404" ) {
236+ invokeStatus = 404 ;
237+ }
238+ const requestMetadata = {
239+ isNextDataReq : routingResult . internalEvent . query . __nextDataReq === "1" ,
240+ initURL : routingResult . initialURL ,
241+ initQuery : convertToQuery ( initialURL . search ) ,
242+ initProtocol : initialURL . protocol ,
243+ defaultLocale : NextConfig . i18n ?. defaultLocale ,
244+ locale : routingResult . locale ,
245+ middlewareInvoke : false ,
246+ // By setting invokePath and invokeQuery we can bypass some of the routing logic in Next.js
247+ invokePath : routingResult . internalEvent . rawPath ,
248+ invokeQuery : routingResult . internalEvent . query ,
249+ // invokeStatus is only used for error pages
250+ invokeStatus,
251+ } ;
252+
228253 try {
229254 //#override applyNextjsPrebundledReact
230255 setNextjsPrebundledReact ( routingResult . internalEvent . rawPath ) ;
231256 //#endOverride
232257
233- // Here we try to apply as much request metadata as possible
234- // We apply every metadata from `resolve-routes` https://github.com/vercel/next.js/blob/canary/packages/next/src/server/lib/router-utils/resolve-routes.ts
235- // and `router-server` https://github.com/vercel/next.js/blob/canary/packages/next/src/server/lib/router-server.ts
236- const initialURL = new URL ( routingResult . initialURL ) ;
237- let invokeStatus : number | undefined ;
238- if ( routingResult . internalEvent . rawPath === "/500" ) {
239- invokeStatus = 500 ;
240- } else if ( routingResult . internalEvent . rawPath === "/404" ) {
241- invokeStatus = 404 ;
242- }
243- const requestMetadata = {
244- isNextDataReq : routingResult . internalEvent . query . __nextDataReq === "1" ,
245- initURL : routingResult . initialURL ,
246- initQuery : convertToQuery ( initialURL . search ) ,
247- initProtocol : initialURL . protocol ,
248- defaultLocale : NextConfig . i18n ?. defaultLocale ,
249- locale : routingResult . locale ,
250- middlewareInvoke : false ,
251- // By setting invokePath and invokeQuery we can bypass some of the routing logic in Next.js
252- invokePath : routingResult . internalEvent . rawPath ,
253- invokeQuery : routingResult . internalEvent . query ,
254- // invokeStatus is only used for error pages
255- invokeStatus,
256- } ;
257258 // Next Server
258259 await requestHandler ( requestMetadata ) ( req , res ) ;
259260 } catch ( e : any ) {
260261 // This might fail when using bundled next, importing won't do the trick either
261262 if ( e . constructor . name === "NoFallbackError" ) {
262- // Do we need to handle _not-found
263- // Ideally this should never get triggered and be intercepted by the routing handler
264- await tryRenderError ( "404" , res , routingResult . internalEvent ) ;
263+ await handleNoFallbackError ( req , res , routingResult , requestMetadata ) ;
264+ } else {
265+ error ( "NextJS request failed." , e ) ;
266+ await tryRenderError ( "500" , res , routingResult . internalEvent ) ;
267+ }
268+ }
269+ }
270+
271+ async function handleNoFallbackError (
272+ req : IncomingMessage ,
273+ res : OpenNextNodeResponse ,
274+ routingResult : RoutingResult ,
275+ metadata : Record < string , unknown > ,
276+ index = 1 ,
277+ ) {
278+ if ( index >= 5 ) {
279+ await tryRenderError ( "500" , res , routingResult . internalEvent ) ;
280+ return ;
281+ }
282+ if ( index >= routingResult . resolvedRoutes . length ) {
283+ await tryRenderError ( "404" , res , routingResult . internalEvent ) ;
284+ return ;
285+ }
286+ try {
287+ await requestHandler ( {
288+ ...routingResult ,
289+ invokeOutput : routingResult . resolvedRoutes [ index ] . route ,
290+ ...metadata ,
291+ } ) ( req , res ) ;
292+ } catch ( e : any ) {
293+ if ( e . constructor . name === "NoFallbackError" ) {
294+ await handleNoFallbackError ( req , res , routingResult , metadata , index + 1 ) ;
265295 } else {
266296 error ( "NextJS request failed." , e ) ;
267297 await tryRenderError ( "500" , res , routingResult . internalEvent ) ;
0 commit comments