-
Notifications
You must be signed in to change notification settings - Fork 176
Closed
Labels
bugSomething isn't workingSomething isn't working
Description
Describe the bug
Node.js version: v22.14.0
OS version: macOS Sequoia 15.5
Description:
Router middleware applied via .use() fails to execute on any routes when the router prefix contains path parameters. This worked correctly in v13.1.1 but is broken in v14.0.0.
Actual behavior
Router middleware executes for static path prefixes (/api/apps), but not for prefixes that include a path parameter (/api/apps/:appId).
Expected behavior
Router middleware applied via .use() should run for all routes in a router, regardless of whether the router prefix includes a path parameter.
Code to reproduce
import Router from "@koa/router";
function authorize() {
return async (ctx, next) => {
console.log(`Middleware executed for ${ctx.method} ${ctx.path}`);
ctx.state.authorized = "AUTHORIZED";
await next();
};
}
// This router works (prefix has no parameters)
export const appsRouter = new Router({
prefix: "/api/apps",
})
.use(authorize())
.get("/", async (ctx) => {
// Middleware runs
ctx.body = { authorized: ctx.state.authorized };
})
.get("/:id", async (ctx) => {
// Middleware runs
ctx.body = { authorized: ctx.state.authorized };
});
// This router fails (prefix contains path parameter)
export const appSettingsRouter = new Router({
prefix: "/api/apps/:appId/settings",
})
.use(authorize())
.get("/", async (ctx) => {
// Middleware does not run, so `ctx.state.authorized` is undefined
ctx.body = { authorized: ctx.state.authorized };
});Failing Test
it('executes middleware for routes when prefix contains path parameters', async () => {
const app = new Koa();
// Test middleware execution with path parameter in prefix
const appSettingsRouter = new Router({
prefix: '/api/apps/:appId/settings'
});
// Track middleware execution
let middlewareExecuted = false;
appSettingsRouter
.use((ctx, next) => {
middlewareExecuted = true;
ctx.state.authorized = 'AUTHORIZED';
return next();
})
.get('/', (ctx) => {
ctx.body = {
authorized: ctx.state.authorized,
middlewareRan: middlewareExecuted,
appId: ctx.params.appId
};
})
.get('/:settingId', (ctx) => {
ctx.body = {
authorized: ctx.state.authorized,
middlewareRan: middlewareExecuted,
appId: ctx.params.appId,
settingId: ctx.params.settingId
};
});
app.use(appSettingsRouter.routes());
// Test first route
middlewareExecuted = false;
const res1 = await request(http.createServer(app.callback()))
.get('/api/apps/123/settings')
.expect(200);
assert.strictEqual(res1.body.authorized, 'AUTHORIZED', 'Middleware should set authorized state');
assert.strictEqual(res1.body.middlewareRan, true, 'Middleware should have executed');
assert.strictEqual(res1.body.appId, '123', 'Should capture appId param');
// Test second route with additional parameter
middlewareExecuted = false;
const res2 = await request(http.createServer(app.callback()))
.get('/api/apps/456/settings/theme')
.expect(200);
assert.strictEqual(res2.body.authorized, 'AUTHORIZED', 'Middleware should set authorized state');
assert.strictEqual(res2.body.middlewareRan, true, 'Middleware should have executed');
assert.strictEqual(res2.body.appId, '456', 'Should capture appId param');
assert.strictEqual(res2.body.settingId, 'theme', 'Should capture settingId param');
});Checklist
- I have searched through GitHub issues for similar issues.
- I have completely read through the README and documentation.
- I have tested my code with the latest version of Node.js and this package and confirmed it is still not working.
skubot, AaronMoat, tadhglewis, motet-a, Sadiqali-Zaveri and 1 more
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working