diff --git a/README.md b/README.md index e1ddba0..528159f 100644 --- a/README.md +++ b/README.md @@ -295,8 +295,9 @@ These are the available config options for the middleware/plugin functions. All // Used if useHeader/echoHeader is set to true. headerName: 'X-Request-Id', // A custom function to generate your request ids (default: UUID v1). + // Framework-specific request object is passed as the argument, so it could be optionally used to calculate the id. // Ignored if useHeader is set to true. - requestIdFactory: () => 'Your request id', + requestIdFactory: (req) => 'Your request id', // Use request id generated by Fastify instead of generating a new id. // Only available for the Fastify plugin. useFastifyRequestId: false, diff --git a/index.d.ts b/index.d.ts index 96f012f..5c23377 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,6 +1,6 @@ import { IncomingMessage, ServerResponse } from 'http' -export type RequestIdFactory = () => unknown +export type RequestIdFactory = (req?: IncomingMessage|any) => unknown export interface IOptions { // Default: false diff --git a/src/rtracer.js b/src/rtracer.js index cf54be1..42da5c7 100644 --- a/src/rtracer.js +++ b/src/rtracer.js @@ -42,7 +42,7 @@ const expressMiddleware = (setResHeaderFn) => { return ({ useHeader = false, headerName = 'X-Request-Id', - requestIdFactory = uuidv1, + requestIdFactory, echoHeader = false } = {}) => { return (req, res, next) => { @@ -50,7 +50,7 @@ const expressMiddleware = (setResHeaderFn) => { if (useHeader) { requestId = req.headers[headerName.toLowerCase()] } - requestId = requestId || requestIdFactory() + requestId = requestId || (requestIdFactory ? requestIdFactory(req) : uuidv1()) if (echoHeader) { setResHeaderFn(res, headerName, requestId) @@ -84,7 +84,7 @@ const fastifyPlugin = (fastify, options, next) => { useHeader = false, headerName = 'X-Request-Id', useFastifyRequestId = false, - requestIdFactory = uuidv1, + requestIdFactory, echoHeader = false } = options @@ -96,7 +96,7 @@ const fastifyPlugin = (fastify, options, next) => { if (useFastifyRequestId) { requestId = requestId || request.id } - requestId = requestId || requestIdFactory() + requestId = requestId || (requestIdFactory ? requestIdFactory(request.raw) : uuidv1()) if (echoHeader) { reply.header(headerName, requestId) @@ -129,7 +129,7 @@ fastifyPlugin[Symbol.for('fastify.display-name')] = pluginName const koaMiddleware = ({ useHeader = false, headerName = 'X-Request-Id', - requestIdFactory = uuidv1, + requestIdFactory, echoHeader = false } = {}) => { return (ctx, next) => { @@ -137,7 +137,7 @@ const koaMiddleware = ({ if (useHeader) { requestId = ctx.request.headers[headerName.toLowerCase()] } - requestId = requestId || requestIdFactory() + requestId = requestId || (requestIdFactory ? requestIdFactory(ctx.request) : uuidv1()) if (echoHeader) { ctx.set(headerName, requestId) @@ -166,7 +166,7 @@ const koaMiddleware = ({ const koaV1Middleware = ({ useHeader = false, headerName = 'X-Request-Id', - requestIdFactory = uuidv1, + requestIdFactory, echoHeader = false } = {}) => { return function * (next) { @@ -174,7 +174,7 @@ const koaV1Middleware = ({ if (useHeader) { requestId = this.request.headers[headerName.toLowerCase()] } - requestId = requestId || requestIdFactory() + requestId = requestId || (requestIdFactory ? requestIdFactory(this.request) : uuidv1()) if (echoHeader) { this.response.set(headerName, requestId) @@ -202,7 +202,7 @@ const hapiPlugin = ({ const { useHeader = false, headerName = 'X-Request-Id', - requestIdFactory = uuidv1, + requestIdFactory, echoHeader = false } = options @@ -211,7 +211,7 @@ const hapiPlugin = ({ if (useHeader) { requestId = request.headers[headerName.toLowerCase()] } - requestId = requestId || requestIdFactory() + requestId = requestId || (requestIdFactory ? requestIdFactory(request) : uuidv1()) als.enterWith(requestId) wrapHttpEmitters(request.raw.req, request.raw.res) diff --git a/tests/express.test.js b/tests/express.test.js index 5927494..87fa523 100644 --- a/tests/express.test.js +++ b/tests/express.test.js @@ -71,6 +71,28 @@ describe('cls-rtracer for Express', () => { }) }) + test('calls request id factory with req', () => { + const app = express() + const idFactory = req => req + + app.use(rTracer.expressMiddleware({ + requestIdFactory: idFactory + })) + + app.get('/test', (req, res) => { + if (req === rTracer.id()) { + res.end() + } else { + res.status(500).end() + } + }) + + return request(app).get('/test') + .then(res => { + expect(res.statusCode).toBe(200) + }) + }) + test('ignores header by default', () => { const app = express() app.use(rTracer.expressMiddleware()) diff --git a/tests/fastify.test.js b/tests/fastify.test.js index 0781779..da33002 100644 --- a/tests/fastify.test.js +++ b/tests/fastify.test.js @@ -71,6 +71,28 @@ describe('cls-rtracer for Fastify', () => { }) }) + test('calls request id factory with req', () => { + const app = Fastify() + const idFactory = req => req + + app.register(rTracer.fastifyPlugin, { + requestIdFactory: idFactory + }) + + app.get('/test', async (request, reply) => { + if (request.raw === rTracer.id()) { + reply.send({}) + } else { + reply.status(500) + } + }) + + return app.ready().then(() => request(app.server).get('/test')) + .then(res => { + expect(res.statusCode).toBe(200) + }) + }) + test('ignores header by default', () => { const app = Fastify() app.register(rTracer.fastifyPlugin) diff --git a/tests/fastifyv2.test.js b/tests/fastifyv2.test.js index b0af021..8bd7dba 100644 --- a/tests/fastifyv2.test.js +++ b/tests/fastifyv2.test.js @@ -86,6 +86,28 @@ for (const type of types) { }) }) + test('calls request id factory with req', () => { + const app = Fastify() + const idFactory = req => req + + register(type, app, { + requestIdFactory: idFactory + }) + + app.get('/test', async (request, reply) => { + if (request.raw === rTracer.id()) { + reply.send({}) + } else { + throw new Error('Invalid') + } + }) + + return app.ready().then(() => request(app.server).get('/test')) + .then(res => { + expect(res.statusCode).toBe(200) + }) + }) + test('ignores header by default', () => { const app = Fastify() register(type, app) diff --git a/tests/hapi.test.js b/tests/hapi.test.js index 1632cec..72f96d2 100644 --- a/tests/hapi.test.js +++ b/tests/hapi.test.js @@ -104,6 +104,30 @@ describe('cls-rtracer for Hapi', () => { expect(res.result.id).toEqual(idFactory()) }) + test('calls request id factory with req', async () => { + const idFactory = req => req + + server = await setupServer({ + options: { + requestIdFactory: idFactory + }, + handler: request => { + if (request === rTracer.id()) { + return 'OK' + } else { + throw new Error('Not OK') + } + } + }) + + const res = await server.inject({ + method: 'get', + url: '/' + }) + + expect(res.statusCode).toBe(200) + }) + test('ignores header by default', async () => { const idInHead = 'id-from-header' let id diff --git a/tests/koa.test.js b/tests/koa.test.js index 11473b3..ecadbf4 100644 --- a/tests/koa.test.js +++ b/tests/koa.test.js @@ -71,6 +71,28 @@ describe('cls-rtracer for Koa', () => { }) }) + test('calls request id factory with req', () => { + const app = new Koa() + const idFactory = req => req + + app.use(rTracer.koaMiddleware({ + requestIdFactory: idFactory + })) + + app.use((ctx) => { + if (ctx.request === rTracer.id()) { + ctx.body = 'OK' + } else { + throw new Error('Not OK') + } + }) + + return request(app.callback()).get('/') + .then(res => { + expect(res.statusCode).toBe(200) + }) + }) + test('ignores header by default', () => { const app = new Koa() app.use(rTracer.koaMiddleware()) diff --git a/tests/koav1.test.js b/tests/koav1.test.js index 794ae04..ed9c766 100644 --- a/tests/koav1.test.js +++ b/tests/koav1.test.js @@ -70,6 +70,27 @@ describe('cls-rtracer for Koa v1', () => { }) }) + test('calls request id factory with req', () => { + const app = new Koa() + const idFactory = req => req + app.use(rTracer.koaV1Middleware({ + requestIdFactory: idFactory + })) + + app.use(function * () { + if (this.request === rTracer.id()) { + this.body = 'OK' + } else { + throw new Error('Not OK') + } + }) + + return request(app.callback()).get('/') + .then(res => { + expect(res.statusCode).toBe(200) + }) + }) + test('ignores header by default', () => { const app = new Koa() app.use(rTracer.koaV1Middleware())