Skip to content

fix(core): run middleware on subpaths next to an all-methods route - #18407

Merged
kamilmysliwiec merged 1 commit into
nestjs:masterfrom
beyondwin:fix/keep-prefix-middleware
Nov 5, 2026
Merged

kamilmysliwiec merged 1 commit into
nestjs:masterfrom
beyondwin:fix/keep-prefix-middleware

Conversation

@beyondwin

Copy link
Copy Markdown
Contributor

PR Checklist

Please check if your PR fulfills the following requirements:

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Other... Please describe:

What is the current behavior?

Since 12.3.3 (#18357), this call no longer runs the middleware for /shop/admin/reports on Express and the node adapter:

consumer
  .apply(AuthMiddleware)
  .forRoutes({ path: 'shop/:id', method: RequestMethod.ALL }, 'shop/admin');

With a middleware that answers 401, GET /shop/admin/reports now returns 200 from the handler. On 12.3.2 the middleware runs for it, because a plain string is mounted with use(), which also matches subpaths. #18357 describes routes declared for a specific method, but its check also removes a plain string next to a parameterized RequestMethod.ALL route. RequestMethod.ALL is app.all / useExact: it matches /shop/admin, not the paths below it.

Issue Number: N/A

What is the new behavior?

A plain string is only removed next to another plain string, as before #18357. A route of a specific method next to RequestMethod.ALL is still removed. The new e2e cases run on Express and the node adapter. Fastify anchors middleware paths, so a string without a wildcard never reaches subpaths there.

Does this PR introduce a breaking change?

  • Yes
  • No

On Express and the node adapter, paths below the string run the middleware again, as on 12.3.2. A path matched by both kept routes, such as /shop/admin, runs it twice on every adapter, also as on 12.3.2 (once on 12.3.3). 77d28b6 accepts the same for /files/:id next to /files/{*path}. On Fastify that double run is the only change. Sharing handledRequests between the all-methods routes of one forRoutes() call would keep one run, but the first mount would then decide what the middleware sees (on Express, no req.params.id when the string comes first), so I left it out.

Other information

I found this reading #18357, not from a report, and a GitHub code search turned up no public app with this exact pair. For an app that has it, a patch upgrade silently skips the middleware on those subpaths.

RequestMethod.ALL is an exact mount. A plain forRoutes string on Express
and the node adapter is a prefix mount, so removing "shop/admin" next to
{ path: "shop/:id", method: ALL } left every path below it without the
middleware.

Keep the string, as 12.3.2 did. The exact path then matches both routes
and runs the middleware twice, as on 12.3.2.
@kamilmysliwiec
kamilmysliwiec merged commit a46202f into nestjs:master Nov 5, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants