Skip to content

Commit 2fe04e3

Browse files
authored
fix(event-handler): moved the response mutation logic to the composeMiddleware function (#4773)
1 parent 0dea57b commit 2fe04e3

File tree

3 files changed

+40
-9
lines changed

3 files changed

+40
-9
lines changed

packages/event-handler/src/rest/Router.ts

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -308,19 +308,11 @@ class Router {
308308
]);
309309

310310
requestContext.params = route?.params ?? {};
311-
const middlewareResult = await middleware({
311+
await middleware({
312312
reqCtx: requestContext,
313313
next: () => Promise.resolve(),
314314
});
315315

316-
// middleware result takes precedence to allow short-circuiting
317-
if (middlewareResult !== undefined) {
318-
requestContext.res = handlerResultToWebResponse(middlewareResult, {
319-
statusCode: getStatusCode(middlewareResult),
320-
resHeaders: requestContext.res.headers,
321-
});
322-
}
323-
324316
return requestContext;
325317
} catch (error) {
326318
this.logger.debug(`There was an error processing the request: ${error}`);

packages/event-handler/src/rest/utils.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import {
3333
SAFE_CHARS,
3434
UNSAFE_CHARS,
3535
} from './constants.js';
36+
import { handlerResultToWebResponse } from './converters.js';
3637

3738
export function getPathString(path: Path): string {
3839
return isString(path) ? path : path.source.replaceAll(/\\\//g, '/');
@@ -230,6 +231,11 @@ export const isExtendedAPIGatewayProxyResult = (
230231
* follows the onion model where middleware executes in order before `next()` and in
231232
* reverse order after `next()`.
232233
*
234+
* When a middleware returns a value(short-circuits), that result becomes the response
235+
* and the `res` object in the `RequestContext` is mutated with that result converted
236+
* to a Web Response preserving any existing headers while applying the status code
237+
* from the middleware result.
238+
*
233239
* @param middleware - Array of middleware functions to compose
234240
* @returns A single middleware function that executes all provided middleware in sequence
235241
*
@@ -294,8 +300,13 @@ export const composeMiddleware = (middleware: Middleware[]): Middleware => {
294300
);
295301
}
296302

303+
// middleware result takes precedence to allow short-circuiting
297304
if (middlewareResult !== undefined) {
298305
result = middlewareResult;
306+
reqCtx.res = handlerResultToWebResponse(middlewareResult, {
307+
statusCode: getStatusCode(middlewareResult),
308+
resHeaders: reqCtx.res.headers,
309+
});
299310
}
300311
};
301312

packages/event-handler/tests/unit/rest/Router/middleware.test.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -777,5 +777,33 @@ describe('Class: Router - Middleware', () => {
777777
expect(result.statusCode).toBe(403);
778778
expect(result.body).toBe('Route middleware response');
779779
});
780+
781+
it('allows post processing middleware to access the response returned early by a pre-processing middleware', async () => {
782+
// Prepare
783+
const app = new Router();
784+
let message = '';
785+
app.get(
786+
'/test',
787+
[
788+
async ({ reqCtx, next }) => {
789+
await next();
790+
const clonedRes = reqCtx.res.clone();
791+
message = (await clonedRes.json()).message;
792+
},
793+
() => {
794+
return Promise.resolve({ message: 'Middleware applied' });
795+
},
796+
],
797+
() => {
798+
return { message: 'Handler applied' };
799+
}
800+
);
801+
802+
// Act
803+
await app.resolve(createTestEvent('/test', 'GET'), context);
804+
805+
// Assess
806+
expect(message).toEqual('Middleware applied');
807+
});
780808
});
781809
});

0 commit comments

Comments
 (0)