From 53e4246ab3901a7010ed8a85783dc82428b3c750 Mon Sep 17 00:00:00 2001 From: Swopnil Dangol Date: Wed, 19 Nov 2025 16:00:14 +0000 Subject: [PATCH 1/3] Moved the response mutation logic to composeMiddleware --- packages/event-handler/src/rest/Router.ts | 10 +------ packages/event-handler/src/rest/utils.ts | 6 ++++ .../tests/unit/rest/Router/middleware.test.ts | 28 +++++++++++++++++++ 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/packages/event-handler/src/rest/Router.ts b/packages/event-handler/src/rest/Router.ts index 40699f804f..96d383ec20 100644 --- a/packages/event-handler/src/rest/Router.ts +++ b/packages/event-handler/src/rest/Router.ts @@ -308,19 +308,11 @@ class Router { ]); requestContext.params = route?.params ?? {}; - const middlewareResult = await middleware({ + await middleware({ reqCtx: requestContext, next: () => Promise.resolve(), }); - // middleware result takes precedence to allow short-circuiting - if (middlewareResult !== undefined) { - requestContext.res = handlerResultToWebResponse(middlewareResult, { - statusCode: getStatusCode(middlewareResult), - resHeaders: requestContext.res.headers, - }); - } - return requestContext; } catch (error) { this.logger.debug(`There was an error processing the request: ${error}`); diff --git a/packages/event-handler/src/rest/utils.ts b/packages/event-handler/src/rest/utils.ts index 780c61a065..2c161d97ed 100644 --- a/packages/event-handler/src/rest/utils.ts +++ b/packages/event-handler/src/rest/utils.ts @@ -33,6 +33,7 @@ import { SAFE_CHARS, UNSAFE_CHARS, } from './constants.js'; +import { handlerResultToWebResponse } from './converters.js'; export function getPathString(path: Path): string { return isString(path) ? path : path.source.replaceAll(/\\\//g, '/'); @@ -294,8 +295,13 @@ export const composeMiddleware = (middleware: Middleware[]): Middleware => { ); } + // middleware result takes precedence to allow short-circuiting if (middlewareResult !== undefined) { result = middlewareResult; + reqCtx.res = handlerResultToWebResponse(middlewareResult, { + statusCode: getStatusCode(middlewareResult), + resHeaders: reqCtx.res.headers, + }); } }; diff --git a/packages/event-handler/tests/unit/rest/Router/middleware.test.ts b/packages/event-handler/tests/unit/rest/Router/middleware.test.ts index 1c5f9c8c96..f618cf42f8 100644 --- a/packages/event-handler/tests/unit/rest/Router/middleware.test.ts +++ b/packages/event-handler/tests/unit/rest/Router/middleware.test.ts @@ -777,5 +777,33 @@ describe('Class: Router - Middleware', () => { expect(result.statusCode).toBe(403); expect(result.body).toBe('Route middleware response'); }); + + it('allows post processing middleware to access the response returned early by a pre processing middleware', async () => { + // Prepare + const app = new Router(); + let message = ''; + app.get( + '/test', + [ + async ({ reqCtx, next }) => { + await next(); + const clonedRes = reqCtx.res.clone(); + message = (await clonedRes.json()).message; + }, + () => { + return Promise.resolve({ message: 'Middleware applied' }); + }, + ], + () => { + return { message: 'Handler applied' }; + } + ); + + // Act + await app.resolve(createTestEvent('/test', 'GET'), context); + + // Assess + expect(message).toEqual('Middleware applied'); + }); }); }); From 13de977bbe2d24949495ef183b9e9453939c42fb Mon Sep 17 00:00:00 2001 From: Swopnil Dangol Date: Wed, 19 Nov 2025 17:42:43 +0000 Subject: [PATCH 2/3] Added some description about the behaviour in the JSDocs --- packages/event-handler/src/rest/utils.ts | 5 +++++ .../event-handler/tests/unit/rest/Router/middleware.test.ts | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/event-handler/src/rest/utils.ts b/packages/event-handler/src/rest/utils.ts index 2c161d97ed..18a8787221 100644 --- a/packages/event-handler/src/rest/utils.ts +++ b/packages/event-handler/src/rest/utils.ts @@ -231,6 +231,11 @@ export const isExtendedAPIGatewayProxyResult = ( * follows the onion model where middleware executes in order before `next()` and in * reverse order after `next()`. * + * When a middleware returns a value(short-circuits), that result becomes the response + * and the `res` object in the `RequestContext` is mutated with that result converted + * to a Web Response preserving any existing headers while applying the status code + * from the middleware result. + * * @param middleware - Array of middleware functions to compose * @returns A single middleware function that executes all provided middleware in sequence * diff --git a/packages/event-handler/tests/unit/rest/Router/middleware.test.ts b/packages/event-handler/tests/unit/rest/Router/middleware.test.ts index f618cf42f8..8be796bdcd 100644 --- a/packages/event-handler/tests/unit/rest/Router/middleware.test.ts +++ b/packages/event-handler/tests/unit/rest/Router/middleware.test.ts @@ -778,7 +778,7 @@ describe('Class: Router - Middleware', () => { expect(result.body).toBe('Route middleware response'); }); - it('allows post processing middleware to access the response returned early by a pre processing middleware', async () => { + it('allows post processing middleware to access the response returned early by a pre- processing middleware', async () => { // Prepare const app = new Router(); let message = ''; From 3ec4d8a8fd5145307c434b375c57ae482f34b183 Mon Sep 17 00:00:00 2001 From: Swopnil Dangol Date: Wed, 19 Nov 2025 18:20:48 +0000 Subject: [PATCH 3/3] Removed whitespace --- .../event-handler/tests/unit/rest/Router/middleware.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/event-handler/tests/unit/rest/Router/middleware.test.ts b/packages/event-handler/tests/unit/rest/Router/middleware.test.ts index 8be796bdcd..fe37c7105e 100644 --- a/packages/event-handler/tests/unit/rest/Router/middleware.test.ts +++ b/packages/event-handler/tests/unit/rest/Router/middleware.test.ts @@ -778,7 +778,7 @@ describe('Class: Router - Middleware', () => { expect(result.body).toBe('Route middleware response'); }); - it('allows post processing middleware to access the response returned early by a pre- processing middleware', async () => { + it('allows post processing middleware to access the response returned early by a pre-processing middleware', async () => { // Prepare const app = new Router(); let message = '';