forked from fastify/fastify-request-context
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
67 lines (54 loc) · 2.28 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
'use strict'
const { AsyncLocalStorage, AsyncResource } = require('node:async_hooks')
const fp = require('fastify-plugin')
const asyncResourceSymbol = Symbol('asyncResource')
const asyncLocalStorage = new AsyncLocalStorage()
const requestContext = {
get: (key) => {
const store = asyncLocalStorage.getStore()
return store ? store[key] : undefined
},
set: (key, value) => {
const store = asyncLocalStorage.getStore()
if (store) {
store[key] = value
}
},
}
function fastifyRequestContext(fastify, opts, next) {
fastify.decorate('requestContext', requestContext)
fastify.decorateRequest('requestContext', { getter: () => requestContext })
fastify.decorateRequest(asyncResourceSymbol, null)
const hook = opts.hook || 'onRequest'
const hasDefaultStoreValuesFactory = typeof opts.defaultStoreValues === 'function'
fastify.addHook(hook, (req, res, done) => {
const defaultStoreValues = hasDefaultStoreValuesFactory
? opts.defaultStoreValues(req)
: opts.defaultStoreValues
asyncLocalStorage.run({ ...defaultStoreValues }, () => {
const asyncResource = new AsyncResource('fastify-request-context')
req[asyncResourceSymbol] = asyncResource
asyncResource.runInAsyncScope(done, req.raw)
})
})
// Both of onRequest and preParsing are executed after the als.runWith call within the "proper" async context (AsyncResource implicitly created by ALS).
// However, preValidation, preHandler and the route handler are executed as a part of req.emit('end') call which happens
// in a different async context, as req/res may emit events in a different context.
// Related to https://github.com/nodejs/node/issues/34430 and https://github.com/nodejs/node/issues/33723
if (hook === 'onRequest' || hook === 'preParsing') {
fastify.addHook('preValidation', (req, res, done) => {
const asyncResource = req[asyncResourceSymbol]
asyncResource.runInAsyncScope(done, req.raw)
})
}
next()
}
module.exports = fp(fastifyRequestContext, {
fastify: '4.x',
name: '@fastify/request-context',
})
module.exports.default = fastifyRequestContext
module.exports.fastifyRequestContext = fastifyRequestContext
module.exports.requestContext = requestContext
// Deprecated
module.exports.fastifyRequestContextPlugin = fastifyRequestContext