This is a follow up on "Fastify + middleware wildcards" #972
According to https://github.com/fastify/fastify/issues/1896#issuecomment-541395980
we can make it work by forRoutes('(.*)') if globalPrefix is set
Also after some digging around, previously it was behaving weirdly with globalPrefix because:
in https://github.com/nestjs/nest/blob/master/packages/core/middleware/middleware-module.ts#L274-L279
const prefix = this.config.getGlobalPrefix();
const basePath = validatePath(prefix);
if (basePath && path === '/*') {
// strip slash when a wildcard is being used
// and global prefix has been set
path = '*';
}
router(basePath + path, proxy);
router was called with /api*,
and then in https://github.com/nestjs/nest/blob/master/packages/platform-fastify/adapters/fastify-adapter.ts#L148
const normalizedPath = path === '/*' ? '' : path;
this.instance.use(normalizedPath, (req, res, next) => {
normalizedPath would never match /*
In summary:
without globalPrefix: this.instance.use('', (req, res, next) => ... works with .forRoutes('*')
with globalPrefix: this.instance.use('/api/(.*)' works with .forRoutes('(.*)')
@Boshen Thanks for the follow up and the positions where the relevant code is. Your suggested solution of
with globalPrefix: this.instance.use('/api/(.)' works with .forRoutes('(.)')
unfortunately still doesn't get the middleware to fire for me. This issue is blocking for me (short of calling the middleware directly in the @Get() getCats method).
@kamilmysliwiec Thanks for your awesome framework. Your suggestion of:
you should rather use interceptors (it should be fairly simple to migrate any existing middleware to an interceptor).
is an approach that I tried so that I can just apply the middleware individually to the routes, whose middleware have decided that they no longer want to be apart of the routes' life(cycle). It appears, however, that _I_ am too simple for the solution. This is how far I've gotten so far:
@Get('/filegroup/:fileGroupId/files/*')
@UseInterceptors(
...useMiddleware(
JwtMiddleware,
AssignDbToRequest,
),
)
getCats() {//}
// Elsewhere
function useMiddleware(...Middlewares: Array<(Type<NestMiddleware>)>): Array<Type<NestInterceptor>> {
return Middlewares.map(Middleware => {
return class extends Middleware implements NestInterceptor {
async intercept(context: ExecutionContext, next) {
const ctx = context.switchToHttp();
const request = ctx.getRequest();
const response = ctx.getResponse();
return this.use(request.raw, response.raw, next.handle);
}
}
});
}
Any pointers to get this semi acceptable workaround working?
@jsdevtom '/filegroup/:fileGroupId/files/*' this won't work for fastify, which uses path-to-regexp under the hood, try '/filegroup/:fileGroupId/files/(.*)'? And if you have global prefix set, try removing it first so its easier to test.
@joey-kendall and I worked on his PR that fixes this issue. Since Fastify is using pathToRegexp under the hood, it seemed like the appropriate solution. @kamilmysliwiec what do you think about this?
@Boshen when I use (.*), the route isn't found. @n8jadams's fix works in my case. The reason for this is because there is a disconnect between the logic used to match the routes and the logic to apply the middleware.
We can theoretically downgrade the path-to-regexp to mimic the behavior of express. Obviously, this older version will have some limitations and will lack some features, but the API will be compatible and consistent.
@kamilmysliwiec I'm not 100% sure what the behavior of express is, but it seems that the proposed PR will leave the existing functionality and expand it to allow for when the global prefix has been set.
@joey-kendall I'm not referring to this PR specifically, but rather to the entire functionality (middleware) when it comes to the fastify integration
@kamilmysliwiec Are you saying that there are more changes to make an API that supports wildcard paths *?
It seems like @joey-kendall 's PR supports that express-like convention for middleware, correctly converting the * to a regex (.*) and passing it to Fastify. However I am not sure if there are any other applicable places in the code that would need to be changed to make that a consistent API convention in Nest.
Or is there another reason why you haven't merged the PR?
in express below code runs successfully (ex post to: http://localhost:3000/a/b/c/d/e.jpg) but when I switched to fastify url not found. I tried wildcard, regex but nothing changed
Post(':path(*)')
@ApiConsumes('multipart/form-data')
@ApiParam({ name: 'path' })
@ApiFile()
async upload(@Param('path') path: string){
}
This has been clarified in the documentation (as part of the v7 release) https://docs.nestjs.com/middleware#route-wildcards

Most helpful comment
@joey-kendall and I worked on his PR that fixes this issue. Since Fastify is using pathToRegexp under the hood, it seemed like the appropriate solution. @kamilmysliwiec what do you think about this?