NestJs fastify middleware: Problems and solutions
Reported here nestjs/nest#11585.
Install instructions
Running this demo:
yarn install
yarn run start
- Open
/
in a browser. This page shows the results of fetching every route for the configured adapter.
Repo scenario
The scenario in this repo is as follows:
SubRouteController (middleware applied)
├── /subroute
└── /subroute/yes
SubRouteNoController
└── /subroute/no
SimilarRoutesController (middleware applied)
├── /similar/test
└── /similar/:id
AbcController (middleware applied)
├── /a
├── /a/b
└── /a/b/c
TestResultsController
└── / (Shows the result of every route)
Test results for all adapters
Path | Expected | Express | Fastify | CustomFastify |
---|---|---|---|---|
/subroute | 1 | 1 | 1 | 1 |
/subroute/no | 0 | 0 | 1 | 0 |
/subroute/yes | 1 | 1 | 2 | 1 |
/similar/test | 1 | 2 | 2 | 1 |
/similar/123 | 1 | 1 | 1 | 1 |
/a | 1 | 1 | 1 | 1 |
/a/b | 1 | 1 | 2 | 1 |
/a/b/c | 1 | 1 | 3 | 1 |
Problems in the existing fastify-adapter
Middleware is executed on subroutes
Registering middleware on a controller that has a /
route, will lead to that middleware executing on all routes regardless of controller. This affects all subroutes of a route with middleware.
This is not a problem using the express adapter.
Test this
- Go to
/subroute/no
or view the results on/
- (optional) Use the
express
adapter inmain.ts
, the middleware will not be executed
See subroute.controller.ts and subroute-no.controller.ts
Middleware is executed multiple times for the same route
If a controller that has middleware applied has n routes that are prefixes of each other, the middleware will be called n times for the most specific URL. It should only be called once.
Test this
Given the following routes: /a
, /a/b
, and /a/b/c
, requesting /a/b/c
results in
{"message":"Middleware executed","fullUrl":"/a/b/c","requestUrl":"/b/c"}
{"message":"Middleware executed","fullUrl":"/a/b/c","requestUrl":"/c"}
{"message":"Middleware executed","fullUrl":"/a/b/c","requestUrl":"/"}
The cause
This behavior is intended for middie which is used by fastify. Instead, hooks should be used. See this issue: fastify/middie#113.
References:
A proposed solution
I have created a modified CustomFastifyAdapter
to use hooks instead of middie, this solves both problems.
This adapter can be tested by editing main.ts.
Middie could be made entirely optional though it might still be required for express middleware.