Skip to content

Conversation

@MiccWan
Copy link
Contributor

@MiccWan MiccWan commented Sep 4, 2025

Summary

Fix .use() middleware being skipped when prefix or .use() path contains parameters in @koa/router v14 (see #202 ).

Problem

  • In v14.0.0, @koa/router introduced a new option pathAsRegExp in Layer, which defaults to true for .use().
  • When pathAsRegExp is true, .use() paths are not processed with path-to-regexp; instead, they are passed directly to new RegExp().
  • As a result, if a .use() path or prefix contains parameters (e.g. /:id, /:version), the generated regex fails, and the .use() middleware is skipped entirely.

Minimal Reproduction

Example

import Router from '@koa/router';
import Koa from 'koa';

const app = new Koa();
const router1 = new Router();

router1
  .use('/:id', (ctx, next) => {
    // this will be skipped in @koa/router v14.0.0
    console.log('router1.use', ctx.params);
    return next();
  })
  .get('/:id', (ctx) => {
    console.log('router1.get', ctx.params);
    ctx.body = 'Hello World!\n';
  });

const router2 = new Router({ prefix: '/api/:version' });
router2
  .use((ctx, next) => {
    // this will be skipped in @koa/router v14.0.0
    console.log('router2.use', ctx.params);
    return next();
  })
  .get('/', (ctx) => {
    console.log('router2.get', ctx.params);
    ctx.body = 'Hello World!\n';
  });

app.use(router1.routes());
app.use(router2.routes());
app.listen(3000, async () => {
  await fetch('http://localhost:3000/123');
  await fetch('http://localhost:3000/api/123');
});

Steps to Reproduce

Run the script directly:

node index.js

Expected Behavior

Console should output:

router1.use { id: '123' }
router1.get { id: '123' }
router2.use { version: '123' }
router2.get { version: '123' }

Actual Behavior

Only the route handlers are triggered, .use() middlewares are skipped:

router1.get { id: '123' }
router2.get { version: '123' }

Changes

  • Updated .use() registration:
    • Replaced the match-all regexp ([^/]*) with an empty string "".
    • This still matches all paths but avoids breaking parameter handling caused by pathAsRegExp.
  • Check this.path is a string instead of checking if it is falsy in setPrefix and Layer.constructor.
  • Tests:
    • Added 2 new tests to cover the parameter-related .use() middleware skipping issue.

Compatibility

  • No breaking changes expected.
  • All official usage patterns remain valid.

Checklist

  • I have ensured my pull request is not behind the main or master branch of the original repository.
  • I have rebased all commits where necessary so that reviewing this pull request can be done without having to merge it first.
  • I have written a commit message that passes commitlint linting.
  • I have ensured that my code changes pass linting tests.
  • I have ensured that my code changes pass unit tests.
  • I have described my pull request and the reasons for code changes along with context if necessary.

@MiccWan MiccWan changed the title fix: parameter in .use and prefix Fix: Ensure .use() middleware works when path or prefix contains parameters Sep 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant