@@ -225,43 +225,73 @@ async function processRequest(
225
225
// https://github.com/dougmoscrop/serverless-http/issues/227
226
226
delete req . body ;
227
227
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
+
228
253
try {
229
254
//#override applyNextjsPrebundledReact
230
255
setNextjsPrebundledReact ( routingResult . internalEvent . rawPath ) ;
231
256
//#endOverride
232
257
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
- } ;
257
258
// Next Server
258
259
await requestHandler ( requestMetadata ) ( req , res ) ;
259
260
} catch ( e : any ) {
260
261
// This might fail when using bundled next, importing won't do the trick either
261
262
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 ) ;
265
295
} else {
266
296
error ( "NextJS request failed." , e ) ;
267
297
await tryRenderError ( "500" , res , routingResult . internalEvent ) ;
0 commit comments