diff --git a/.changeset/olive-buttons-allow.md b/.changeset/olive-buttons-allow.md new file mode 100644 index 000000000..32052ce74 --- /dev/null +++ b/.changeset/olive-buttons-allow.md @@ -0,0 +1,5 @@ +--- +"@opennextjs/aws": patch +--- + +fix: Propagate the status code in middleware rewrites diff --git a/packages/open-next/src/adapters/middleware.ts b/packages/open-next/src/adapters/middleware.ts index ff243d6de..8d247d303 100644 --- a/packages/open-next/src/adapters/middleware.ts +++ b/packages/open-next/src/adapters/middleware.ts @@ -20,6 +20,7 @@ import { import { constructNextUrl } from "../core/routing/util"; import routingHandler, { INTERNAL_EVENT_REQUEST_ID, + INTERNAL_HEADER_REWRITE_STATUS_CODE, INTERNAL_HEADER_INITIAL_URL, INTERNAL_HEADER_RESOLVED_ROUTES, } from "../core/routingHandler"; @@ -86,6 +87,9 @@ const defaultHandler = async ( result.resolvedRoutes, ), [INTERNAL_EVENT_REQUEST_ID]: requestId, + [INTERNAL_HEADER_REWRITE_STATUS_CODE]: String( + result.rewriteStatusCode, + ), }, }, isExternalRewrite: result.isExternalRewrite, diff --git a/packages/open-next/src/core/requestHandler.ts b/packages/open-next/src/core/requestHandler.ts index 3ee1fc89e..51becb872 100644 --- a/packages/open-next/src/core/requestHandler.ts +++ b/packages/open-next/src/core/requestHandler.ts @@ -23,6 +23,7 @@ import { } from "./routing/util"; import routingHandler, { INTERNAL_EVENT_REQUEST_ID, + INTERNAL_HEADER_REWRITE_STATUS_CODE, INTERNAL_HEADER_INITIAL_URL, INTERNAL_HEADER_RESOLVED_ROUTES, MIDDLEWARE_HEADER_PREFIX, @@ -69,6 +70,9 @@ export async function openNextHandler( resolvedRoutes: initialHeaders[INTERNAL_HEADER_RESOLVED_ROUTES] ? JSON.parse(initialHeaders[INTERNAL_HEADER_RESOLVED_ROUTES]) : ([] as ResolvedRoute[]), + rewriteStatusCode: Number.parseInt( + initialHeaders[INTERNAL_HEADER_REWRITE_STATUS_CODE], + ), }; let routingResult: InternalResult | RoutingResult = { diff --git a/packages/open-next/src/core/routing/middleware.ts b/packages/open-next/src/core/routing/middleware.ts index 2d52e6e89..3d97d1110 100644 --- a/packages/open-next/src/core/routing/middleware.ts +++ b/packages/open-next/src/core/routing/middleware.ts @@ -28,6 +28,7 @@ const middleMatch = getMiddlewareMatch( type MiddlewareEvent = InternalEvent & { responseHeaders?: Record; isExternalRewrite?: boolean; + rewriteStatusCode?: number; }; type Middleware = (request: Request) => Response | Promise; @@ -189,5 +190,6 @@ export async function handleMiddleware( cookies: internalEvent.cookies, remoteAddress: internalEvent.remoteAddress, isExternalRewrite, + rewriteStatusCode: statusCode, } satisfies MiddlewareEvent; } diff --git a/packages/open-next/src/core/routing/util.ts b/packages/open-next/src/core/routing/util.ts index ad62d8f1f..77fa2eba6 100644 --- a/packages/open-next/src/core/routing/util.ts +++ b/packages/open-next/src/core/routing/util.ts @@ -413,6 +413,7 @@ export function createServerResponse( }, responseStream, headers, + routingResult.rewriteStatusCode, ); } diff --git a/packages/open-next/src/core/routingHandler.ts b/packages/open-next/src/core/routingHandler.ts index 95502d667..84f9b204d 100644 --- a/packages/open-next/src/core/routingHandler.ts +++ b/packages/open-next/src/core/routingHandler.ts @@ -36,6 +36,7 @@ export const INTERNAL_HEADER_PREFIX = "x-opennext-"; export const INTERNAL_HEADER_INITIAL_URL = `${INTERNAL_HEADER_PREFIX}initial-url`; export const INTERNAL_HEADER_LOCALE = `${INTERNAL_HEADER_PREFIX}locale`; export const INTERNAL_HEADER_RESOLVED_ROUTES = `${INTERNAL_HEADER_PREFIX}resolved-routes`; +export const INTERNAL_HEADER_REWRITE_STATUS_CODE = `${INTERNAL_HEADER_PREFIX}rewrite-status-code`; export const INTERNAL_EVENT_REQUEST_ID = `${INTERNAL_HEADER_PREFIX}request-id`; // Geolocation headers starting from Nextjs 15 @@ -254,6 +255,7 @@ export default async function routingHandler( locale: NextConfig.i18n ? detectLocale(eventOrResult, NextConfig.i18n) : undefined, + rewriteStatusCode: middlewareEventOrResult.rewriteStatusCode, }; } catch (e) { error("Error in routingHandler", e); diff --git a/packages/open-next/src/http/openNextResponse.ts b/packages/open-next/src/http/openNextResponse.ts index 5f2b7a54d..1aca850a5 100644 --- a/packages/open-next/src/http/openNextResponse.ts +++ b/packages/open-next/src/http/openNextResponse.ts @@ -71,8 +71,12 @@ export class OpenNextNodeResponse extends Transform implements ServerResponse { private onEnd: (headers: OutgoingHttpHeaders) => Promise, private streamCreator?: StreamCreator, private initialHeaders?: OutgoingHttpHeaders, + statusCode?: number, ) { super(); + if (statusCode !== undefined) { + this.statusCode = statusCode; + } } // Necessary for next 12 diff --git a/packages/open-next/src/types/open-next.ts b/packages/open-next/src/types/open-next.ts index 210803468..483516f04 100644 --- a/packages/open-next/src/types/open-next.ts +++ b/packages/open-next/src/types/open-next.ts @@ -37,6 +37,7 @@ export type InternalResult = { headers: Record; body: ReadableStream; isBase64Encoded: boolean; + rewriteStatusCode?: number; } & BaseEventOrResult<"core">; export interface StreamCreator { @@ -151,6 +152,8 @@ export interface RoutingResult { // The resolved route after applying rewrites, if used with an external middleware will be defined in x-opennext-resolved-routes header as a json encoded array resolvedRoutes: ResolvedRoute[]; + // The status code applied to a middleware rewrite + rewriteStatusCode?: number; } export interface MiddlewareResult