fastify / help

Need help with Fastify? File an Issue here.
https://www.fastify.io/
64 stars 8 forks source link

Decorators vs. fastify-request-context #759

Open kurtextrem opened 1 year ago

kurtextrem commented 1 year ago

💬 Question here

I have hard time understanding the difference between decorators that reset on every req vs. the fastify-request-context plugin. If my handler looks like:

// Decorate request with a 'user' property
fastify.decorateRequest('user', null)

// Update our property
fastify.addHook('preHandler', (req, reply, done) => {
  req.user = { id: 'system' }
  done()
})

fastify.addHook('onRequest', (req, reply, done) => {
  req.user.id = someCondition ? 'abc' : 'def'
  done();
});

fastify.get('/', (req, reply) => {
  reply.send(`Hello, ${req.user.a}!`) // expect 'abc' or 'def'
})

How would it happen that req.user gets overriden? Am I missing something? E.g. the code above should reflect the example in https://github.com/thorough-developer/fastify-http-context. The readme in fastify-http-context and fastify-request-context mention that this prevents overriding things when multiple requests hit the same API endpoint - but is this correct? So if e.g. "/user/*" is waiting for the DB to load data for user X, and then some accesses user Y, it could happen that we get back "Hello, X" for the Y route?

kibertoad commented 1 year ago

@kurtextrem fastify-request-context is based on AsyncLocalStorage, so you can think about it in terms of ThreadLocal in java - you have a guarantee that certain value is scoped to one request, even if you are accessing it directly from the store, and not through request itself. request decorators don't use anything fancy under-the-hood, they are reliant on you accessing something on the request instance itself. If you have reference to your request instance, you don't need fastify-request-context, as AsyncLocalStorage definitely brings performance overhead.

kurtextrem commented 1 year ago

@kibertoad Thank you! So, with fastify-request-context you could potentially avoid passing the request instance to every function - makes sense. I see the use now.

jsumners commented 1 year ago

If you have decorated your request with a function, that function's this is mapped to the request.