HTTP Request Context
Set and Get request-scoped context anywhere.
Requirement
Nodejs version >= 8.2.0
This module uses the newer async_hooks API which is considered Experimental
by Nodejs.
Options
Option | Description | Type | Default |
---|
interval | remove expired callstack interval(s) | Number | 10 |
expire | callstack expire time(s) | Number | 150 |
removeAfterFinish | remove callstack after http.ServerResponse finish | Boolean | false |
removeAfterClose | remove callstack after http.ServerResponse close | Boolean | false |
options.interval
Remove expired callstack interval, used like setInterval(removeExpiredCallstack, interval)
.
options.expire
Callstack expire time, must be longer than full lifecycle of a request.
options.removeAfterFinish
It will actively remove the relevant callstack after http.ServerResponse finish.
If set to true
, you can get the context synchronously in the finish event, but not asynchronous. The benefit is that it can improve the performance of this middleware.
options.removeAfterClose
This is very similar to options.removeAfterFinish
, the difference is that after the close event.
Please Note! if set to true
, in some cases, the close event may be caused by the client terminating the request, after the close event, we may still use the context after the incomplete asynchronous operation is completed, this will result in loss of context.
Init Middleware
Do not use any middleware that contains asynchronous operations before this middleware.
httpRequestContext.middleware(options)
Init Express middleware.httpRequestContext.koaMiddleware(options)
Init Koa middleware.
Set Context
httpRequestContext.set(key, value)
Set context anywhere.httpRequestContext.set({ key: value })
This is also OK.
Get Context
httpRequestContext.get(key)
Get the [key]
attribute of the context.httpRequestContext.get()
Gets an object containing all context properties.
How to Use
see example here.
Install
npm install http-request-context --save
Express
Init
import httpRequestContext from 'http-request-context'
app.use(httpRequestContext.middleware())
Set Context
import httpRequestContext from 'http-request-context'
app.use((req, res, next) => {
setTimeout(() => {
httpRequestContext.set('foo', 'bar')
next()
}, 100)
})
Get Context
import httpRequestContext from 'http-request-context'
httpRequestContext.get('foo')
Koa
Init
import httpRequestContext from 'http-request-context'
app.use(httpRequestContext.koaMiddleware())
Set Context
import httpRequestContext from 'http-request-context'
app.use(async (ctx, next) => {
await new Promise(resolve => {
setTimeout(() => {
httpRequestContext.set('user', 'user')
resolve()
}, 300)
})
await next()
})
Get Context
import httpRequestContext from 'http-request-context'
httpRequestContext.get('foo')
Lost Context Tips
http.ServerResponse close event
Sometimes, when client terminal request by close window or reload page, it will cause http.ServerResponse emit 'close' event, this event is trigger by root, so it break away from current request scope, in this case, we can add res
(express) or ctx.res
(koa) parameter to get context function to ensure context can be tracked, as follows:
res.on('close', () => {
console.log('close', httpRequestContext.get('foo', res))
})
ctx.res.on('close', () => {
console.log('close', httpRequestContext.get('foo', ctx.res))
})
MySQL
If you init mysql connect before http server start, you may get context undefined in mysql query callback scope.
googleapis/cloud-trace-nodejs #946
nodejs/node #22360
mysqlConnection.query('SELECT * FROM table', (error, results, fields) => {
httpRequestContext.get('foo')
})
You can use util.promisify to avoid it.
util.promisify(mysqlConnection.query).bind(mysqlConnection)('SELECT * FROM table')
.then((results, fields) => {
httpRequestContext.get('foo')
})
.catch(error => {})