-
-
Notifications
You must be signed in to change notification settings - Fork 7.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fastify Adapter Middleware Properties on a Different Context #8837
Comments
It should also be noted that with fastify, this is the same behavior. const fastify = require("fastify");
const middie = require("middie");
const start = async () => {
try {
const app = fastify();
await app.register(middie);
app.use((req, res, next) => {
req.custom = "something else";
next();
});
app.get("/", (req, reply) => {
return {
regular: req.custom,
raw: req.raw.custom,
};
});
await app.listen(3030);
} catch (err) {
process.stderr.write(err.toString());
process.exit(1);
}
};
start(); curl http://localhost:3030
{"raw":"something else"} I'm not 100% convinced this is a bug as this is how it seems Fastify is expected to act. However, we should probably make a note that attaching properties to the @kamilmysliwiec thoughts? |
|
Thanks for looking into this issue @jmcdo29 🙌
This is correct and it's expected behavior. Fastify passes raw (unwrapped) Request & Response objects to middleware functions while route handlers receive wrapped FastifyReply and FastifyRequest objects.
We should probably add a hint to the docs as it clearly led to confusion.
Side note: AsyncLocalStorage relies on the |
Spent some time trying to reproduce the ALS issue, here is a minimal repro: https://github.com/B4nan/nest-fastify-als I don't think that OP in this issue is about the same, the reproduction is just attaching things to |
@B4nan what if you use pure Fastify instead of Nest? Does this happen as well? |
Pure fastify does not support middlewares, right? edit: probably via this? https://github.com/fastify/middie |
Correct @B4nan, using |
Looks like it fails with bare bones fastify+middie too, so probably not nest related. |
If people are passing through here, here is the Node Core issue about it: nodejs/node#41285. |
FWIW I don't think this is totally fixable within Fastify, Nest or Node.js. For your use case you should be using |
After some investigation, I think the root cause of the problem is that Nest.js starts its own AsyncLocalStorage after body-parser has done its job with express, and before Fastify has parsed the body. Note that entering the AsyncLocalStorage before doing the body parsing has the same effect with express (and it will lose context): 'use strict'
const { AsyncLocalStorage } = require('async_hooks')
const express = require('express')
const storage = new AsyncLocalStorage()
let counter = 0
const app = express()
app.use((req, res, next) => {
const id = counter++
console.log('In Middleware with id ' + id)
storage.run({ id }, function () {
next()
})
})
app.use(require('body-parser').json()) // try moving this before the above middleware
app.post('/', (req, res) => {
const store = storage.getStore()
console.log('store is', store)
res.end(JSON.stringify(store))
})
app.listen(3000) All things considered, I think the best solution for Nest is to register middie in a different hook, either |
Thanks for chiming in @mcollina!
Could you elaborate more on this? Nest internally doesn't use the
This is where we currently register |
I'm unsure. Apparently quite a few Nest.js users are (possibly in combination with MikroORM?) and they are reporting this issues and others on Fastify repositories.
In Nest you register the body-parser middleware before everything: https://github.dev/nestjs/nest/blob/411ef5e237b487c447e6b28fafaf3914ffa75778/packages/platform-fastify/adapters/fastify-adapter.ts#L459. However my default Middie executes the middlewares during the Fastify onRequest hook, before body parsing. Due to nodejs/node#41285, parsing any body would lose context.
I forgot to do it in Middie, we just shipped it as https://github.com/fastify/middie/tree/v5.4.0. This is an example: const fastify = require('fastify')()
fastify
.register(require('middie'), { hook: 'preHandler' })
.register(subsystem)
async function subsystem (fastify, opts) {
fastify.addHook('onRequest', async (req, reply) => {
console.log('first')
})
fastify.use((req, res, next) => {
console.log('third')
next()
})
fastify.addHook('onRequest', async (req, reply) => {
console.log('second')
})
fastify.addHook('preHandler', async (req, reply) => {
console.log('fourth')
})
} Anyway, this issue can be closed as I shipped Fastify v3.25.2 that should fix it. |
I think it's due to MikroORM that use ALS.
❤️ 🙌
I'll look into that |
Note that the issue with ALS is now addressed in latest fastify, but nest has the fastify version locked to older one, so on nest level the issue is still there. https://github.com/nestjs/nest/blob/master/packages/platform-fastify/package.json#L20 |
@kamilmysliwiec @jmcdo29 can we please bump the version of fastify and ship new version of the platform? or is there anything blocking? |
@B4nan A new version has been published yesterday |
Well, but the fastify version in master is still the same 🤷 https://github.com/nestjs/nest/blob/master/packages/platform-fastify/package.json#L20 |
That's odd. Dependabot/renovate should have updated deps automatically. I'll look into this |
Another bump that the fastify version in master is still old. Can we reopen this? I can understand you keep forgetting about closed issues. Or do you want me to PR this? |
It seems that Renovate got stuck for some reason. I haven't had enough time to investigate it yet so feel free to create a PR and I'll merge it asap. |
I am sure it won't get unstuck automatically (using renovate myself for quite some time), if you for some reason closed upgrade PR for fastify, it won't create new one unless there is new major version. |
Well, but you have opened PR for that :D |
If you check out this issue #4944 you'll notice that it got stuck even though I haven't closed "upgrade PR" for fastify. Luckily it seems that Dependabot created a PR for this so it will surely get merged very shortly. |
From what I know, dependabot does not privide any automerge (it was there but they removed it). Why don't you just push the button, given the tests are green? :] Also I don't see any fastify PR from renovate, only presence of the work |
This is exactly what indicates that Renovate is stuck. |
Is there an existing issue for this?
Current behavior
There are (closed) existing issues for this, all without reproductions. (#8234 #8809 along with iamolegga/nestjs-pino#546 and mikro-orm/mikro-orm#2531) On to the issue
When running middleware, it's common for us to want to attach properties to the
req
object to be able to access them later. Pino and MikroORM both do this, and apparently useAsyncLocalStorage
to help stay away from needing toREQUEST
scope providers (which is honestly really nice). With Express, this works just fine, because Express'sRequest
is Node'sIncomingRequest
object. With Fastify, however, it is aFastifyRequest
which is a wrapper aroundIncomingRequest
. With the use ofmiddie
we are able to apply express-like middleware to Fastify, which helps the merging of the frameworks inside of Nest. It appears though thatreq.custom
applies to different property than expected, meaning that the retrieval by ALS doesn't work properlyWhen running the following Nest middleware
we have two different behaviors.
In Express
We can do
@Req()
and get the property withreq.custom
in a controllerIn Fastify
We an do
@Req()
and get the property withreq.raw.custom
in a controllerMinimum reproduction code
https://github.com/jmcdo29/context-fastify-middleware
Steps to reproduce
pnpm i
/npm i
/yarn
pnpm test:e2e
/npm run test:e2e
/yarn test:e2e
See the test fail
Expected behavior
Regardless of the adapter used
req.custom
should get the custom propertyPackage
@nestjs/common
@nestjs/core
@nestjs/microservices
@nestjs/platform-express
@nestjs/platform-fastify
@nestjs/platform-socket.io
@nestjs/platform-ws
@nestjs/testing
@nestjs/websockets
Other package
No response
NestJS version
8.2.4
Packages versions
[System Information]
OS Version : Linux 5.15
NodeJS Version : v16.13.0
PNPM Version : 6.21.0
[Nest CLI]
Nest CLI Version : 8.1.6
[Nest Platform Information]
platform-express version : 8.2.4
platform-fastify version : 8.2.4
schematics version : 8.0.5
testing version : 8.2.4
common version : 8.2.4
core version : 8.2.4
cli version : 8.1.6
Node.js version
16.13.0
In which operating systems have you tested?
Other
I'll start looking into what we can do with
middie
to alleviate this. Just thought I should get a proper minimum reproduction for this as it seems to affect several other packages, but no one has been able to provide something yetThe text was updated successfully, but these errors were encountered: