diff --git a/packages/express-wrapper/src/middleware.ts b/packages/express-wrapper/src/middleware.ts index 947760f7..38fd12e3 100644 --- a/packages/express-wrapper/src/middleware.ts +++ b/packages/express-wrapper/src/middleware.ts @@ -216,5 +216,5 @@ export async function runMiddlewareChainIgnoringResults< } }); } - return input; + return { ...input, ...(req.body || {}) }; } diff --git a/packages/express-wrapper/test/middleware.test.ts b/packages/express-wrapper/test/middleware.test.ts index 397f4e03..938b3938 100644 --- a/packages/express-wrapper/test/middleware.test.ts +++ b/packages/express-wrapper/test/middleware.test.ts @@ -40,6 +40,38 @@ test('should handle errors passed to next()', async () => { ); }); +test('middleware that modifies req should pass changes through chain', async () => { + const testReq = { body: {}, headers: {} } as express.Request; + const testRes = {} as express.Response; + + const modifyReqMiddleware: express.RequestHandler = (req, _res, next) => { + (req as any).userId = 123; + next(); + }; + + const checkReqMiddleware: express.RequestHandler = (req, _res, next) => { + assert.equal( + (req as any).userId, + 123, + 'userId should still be on req in second middleware', + ); + next(); + }; + + await runMiddlewareChain( + { foo: 'test' }, + [modifyReqMiddleware, noopMiddleware, checkReqMiddleware], + testReq, + testRes, + ); + + assert.equal( + (testReq as any).userId, + 123, + 'req should still have userId after chain', + ); +}); + test('should work with middleware that return values', async () => { const result = await runMiddlewareChain( { foo: 'test' }, diff --git a/packages/express-wrapper/test/server.test.ts b/packages/express-wrapper/test/server.test.ts index 03461f2e..5dd06366 100644 --- a/packages/express-wrapper/test/server.test.ts +++ b/packages/express-wrapper/test/server.test.ts @@ -276,3 +276,59 @@ test('should return a 400 when request fails to decode', async () => { assert(response.body.error.startsWith('Invalid value undefined supplied to')); }); + +test('middleware that modifies req.body should reach handler even without routeHandler()', async () => { + const PostWithData = httpRoute({ + path: '/data', + method: 'POST', + request: httpRequest({ + body: { + originalField: t.string, + addedByMiddleware: optional(t.string), + }, + }), + response: { + 200: t.type({ + originalField: t.string, + addedByMiddleware: optional(t.string), + }), + }, + }); + + const testApiSpec = apiSpec({ + 'test.route': { + post: PostWithData, + }, + }); + + const modifyBodyMiddleware: express.RequestHandler = (req, _res, next) => { + req.body.addedByMiddleware = 'ADDED'; + next(); + }; + + const handler = async (params: { originalField: string; addedByMiddleware?: string }) => { + return { + type: 200, + payload: { + originalField: params.originalField, + addedByMiddleware: params.addedByMiddleware, + }, + } as const; + }; + + const app = createServer(testApiSpec, (app: express.Application) => { + app.use(express.json()); + return { + 'test.route': { + post: { middleware: [modifyBodyMiddleware], handler }, + }, + }; + }); + + const response = await supertest(app) + .post('/data') + .send({ originalField: 'test' }) + .expect(200); + + assert.equal(response.body.addedByMiddleware, 'ADDED', 'addedByMiddleware should be present because req.body is part of req.decoded'); +});