From 4349735823025cdcecd181826f492919354d316a Mon Sep 17 00:00:00 2001 From: Taku Amano Date: Wed, 13 Nov 2024 17:31:06 +0900 Subject: [PATCH] fix(middleware/combine): prevent `c.req.routeIndex` from being changed (#3663) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * test(middleware/combine): add test for every middleware Co-authored-by: Paweł Dąbrowski * refactor(compose): Loosen `compose` parameter types The current implementation of `compose` does not use some elements of the received middleware, so they do not have to be passed on. * fix(middleware/combine): prevent `c.req.routeIndex` from being changed --------- Co-authored-by: Paweł Dąbrowski --- src/compose.ts | 3 +-- src/middleware/combine/index.test.ts | 16 ++++++++++++++++ src/middleware/combine/index.ts | 27 +++++++++++++++------------ 3 files changed, 32 insertions(+), 14 deletions(-) diff --git a/src/compose.ts b/src/compose.ts index a4e1481c..d0e3b7fb 100644 --- a/src/compose.ts +++ b/src/compose.ts @@ -1,5 +1,4 @@ import { Context } from './context' -import type { ParamIndexMap, Params } from './router' import type { Env, ErrorHandler, NotFoundHandler } from './types' /** @@ -31,7 +30,7 @@ interface ComposeContext { * @returns {(context: C, next?: Function) => Promise} - A composed middleware function. */ export const compose = ( - middleware: [[Function, unknown], ParamIndexMap | Params][], + middleware: [[Function, unknown], unknown][] | [[Function]][], onError?: ErrorHandler, onNotFound?: NotFoundHandler ): ((context: C, next?: Function) => Promise) => { diff --git a/src/middleware/combine/index.test.ts b/src/middleware/combine/index.test.ts index fbeea63f..f86391dc 100644 --- a/src/middleware/combine/index.test.ts +++ b/src/middleware/combine/index.test.ts @@ -166,6 +166,22 @@ describe('every', () => { expect(await res.text()).toBe('Hello Middleware 1') expect(middleware2).not.toBeCalled() }) + + it('Should pass the path params to middlewares', async () => { + const app = new Hono() + app.use('*', nextMiddleware) + const paramMiddleware: MiddlewareHandler = async (c) => { + return c.json(c.req.param(), 200) + } + + app.use('/:id', every(paramMiddleware)) + app.get('/:id', (c) => { + return c.text('Hello World') + }) + + const res = await app.request('http://localhost/123') + expect(await res.json()).toEqual({ id: '123' }) + }) }) describe('except', () => { diff --git a/src/middleware/combine/index.ts b/src/middleware/combine/index.ts index 3f8dee81..2a258bc3 100644 --- a/src/middleware/combine/index.ts +++ b/src/middleware/combine/index.ts @@ -89,19 +89,22 @@ export const some = (...middleware: (MiddlewareHandler | Condition)[]): Middlewa * ``` */ export const every = (...middleware: (MiddlewareHandler | Condition)[]): MiddlewareHandler => { - const wrappedMiddleware = middleware.map((m) => async (c: Context, next: Next) => { - const res = await m(c, next) - if (res === false) { - throw new Error('Unmet condition') - } - return res - }) - - const handler = async (c: Context, next: Next) => - compose(wrappedMiddleware.map((m) => [[m, undefined], c.req.param()]))(c, next) - return async function every(c, next) { - await handler(c, next) + const currentRouteIndex = c.req.routeIndex + await compose( + middleware.map((m) => [ + [ + async (c: Context, next: Next) => { + c.req.routeIndex = currentRouteIndex // should be unchanged in this context + const res = await m(c, next) + if (res === false) { + throw new Error('Unmet condition') + } + return res + }, + ], + ]) + )(c, next) } }