-
-
Notifications
You must be signed in to change notification settings - Fork 662
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
app.route includes middleware from previous groups #2988
Comments
I think this is not a bug. If I organize your code, it will look like this: import { Hono } from "hono";
const app = new Hono();
app.use(async (_, next) => {
console.log("Middleware A start");
await next();
console.log("Middleware A end");
});
app.get("/a", (c) => {
return c.text("A");
});
app.use(async (_, next) => {
console.log("Middleware B start");
await next();
console.log("Middleware B end");
});
app.get("/b", (c) => {
return c.text("B");
});
export default app; Middleware is executed in the order in which it is registered, but in the case of |
That doesn't say anything about .route(), I'd expect middleware to only apply to the group.
Please read the additional information section of the issue, this was originally just one middleware repeated in each group for typescript reasons. I understand how it's happening, this behaviour is unintuitive though and doesn't seem useful. We can create route groups with scoped paths but they still leak middleware to the rest of the app. Expanding the example with groups this is how I expected it to work: const router = new Hono()
.use(async (_, next) => {
console.log('middleware 2 start')
await next()
console.log('middleware 2 end')
})
.get('/1', (c) => {
console.log('handler 1')
return c.text('Hello!')
})
app.use(async (_, next) => {
console.log('middleware 1 start')
await next()
console.log('middleware 1 end')
})
app.route('/', router)
app.use(async (_, next) => {
console.log('middleware 3 start')
await next()
console.log('middleware 3 end')
})
app.get('/2', (c) => {
console.log('handler 2')
return c.text('Hello!')
})
|
I found a feature request for something similar, I don't see why this shouldn't just be the default behaviour though: #1674 |
This would also solve #2249 |
And #2794 app
.route('/foo/', new Hono().use(authMiddleware).route('/', PageFoo))
.get('/protected', authMiddleware, (ctx) => ctx.text('protected', 200)) |
Hi @KaelWD Thank you for the issue. This is not a bug. But as you feel, it may not be intuitive. I'll consider this issue for a while. |
The types actually already work like this: const router = new Hono()
.use<{
Variables: {
test: 'override'
}
}>(async (c, next) => {
c.set('test', 'override')
await next()
})
const app = new Hono()
.use<{
Variables: {
test: 'root'
}
}>(async (c, next) => {
c.set('test', 'root')
await next()
})
.route('/', router)
.get('/test', async (c) => {
const test = c.get('test')
// ^? "root"
return c.text(test) // 'override', type doesn't match
}) |
Hi @KaelWD Thanks. Can you create a separate issue? |
Hmmm, this is a difficult one. There is no doubt that the current behaviour is in itself a specification. Internal specification of
|
I reproduced this problem, but I found it only happens if the grouped routes contain a path. So the problem doesn't occur in this code: const routerA = new Hono()
.use(async (c, next) => {
console.log('Middleware A')
await next()
})
.get(async c => {
return c.text('A')
})
const routerB = new Hono()
.use(async (c, next) => {
console.log('Middleware B')
await next()
})
.get(async c => {
return c.text('B')
})
const app = new Hono()
.route('/a', routerA) // logs only "Middleware A"
.route('/b', routerB) // logs only "Middleware B" Although the behavior with paths is unexpected, I prefer to write my routes without the path. I believe this is a cleaner separation of concerns. So I'm happy. EDIT: I see the problem with path parameters and types now. |
I got into this issue as well... I'm registering a public router, an authenticated router and a management router. When I call a non-existing endpoint the management middleware is hit, I expect this middleware to only be hit by the registered routes from the management router. |
What version of Hono are you using?
4.4.6
What runtime/platform is your app running on?
Node
What steps can reproduce the bug?
What is the expected behavior?
calling GET /a logs "Middleware A"
calling GET /b logs "Middleware B"
What do you see instead?
calling GET /a logs "Middleware A"
calling GET /b logs "Middleware A" "Middleware B"
Additional information
I was trying to avoid #2987 with a pattern like this instead of ContextVariableMap but appMiddleware ends up being called multiple times in later groups
The text was updated successfully, but these errors were encountered: