@villedemontreal/correlation-id
Version:
Express middleware to set a correlation in Express. The correlation id will be consistent across async calls within the handling of a request.
272 lines • 13.4 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const chai_1 = require("chai");
const express = require("express");
const http_header_fields_typed_1 = require("http-header-fields-typed");
const request = require("supertest");
const correlationIdService_1 = require("../services/correlationIdService");
const testingConfigurations_1 = require("../utils/testingConfigurations");
const correlationIdMiddleware_1 = require("./correlationIdMiddleware");
function delay(millis) {
return new Promise((resolve) => setTimeout(() => {
resolve();
}, millis));
}
// ==========================================
// Set Testing configurations
// ==========================================
(0, testingConfigurations_1.setTestingConfigurations)();
const uuidMatcher = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
// ==========================================
// Correlation ID service
// ==========================================
// tslint:disable-next-line: max-func-body-length
describe('Correlation ID Middleware', () => {
it('should generate correlation id if it doesnt exists', async () => {
const app = express();
app.use((0, correlationIdMiddleware_1.createCorrelationIdMiddleware)());
app.get('/', (req, res) => {
const actual = correlationIdService_1.correlationIdService.getId();
chai_1.assert.match(actual, uuidMatcher);
res.end();
});
await request(app).get('/').send();
});
it('should get correlation id from incoming request', async () => {
const testId = 'correlation-id-123';
const app = express();
app.use((0, correlationIdMiddleware_1.createCorrelationIdMiddleware)());
app.get('/', (req, res) => {
const actual = correlationIdService_1.correlationIdService.getId();
chai_1.assert.strictEqual(actual, testId, 'getId() should return id from x-correlation-id header of inbound request');
res.end();
});
await request(app).get('/').set(http_header_fields_typed_1.default.X_CORRELATION_ID, testId).send();
});
it('should maintain correlation id with async callbacks', async () => {
const testId = 'correlation-id-123';
let actual = '';
let actual2 = '';
const app = express();
app.use((0, correlationIdMiddleware_1.createCorrelationIdMiddleware)());
app.get('/', async (req, res, next) => {
actual = correlationIdService_1.correlationIdService.getId();
setTimeout(() => {
actual2 = correlationIdService_1.correlationIdService.getId();
res.end();
}, 250);
});
chai_1.assert.isUndefined(correlationIdService_1.correlationIdService.getId());
await request(app).get('/').set(http_header_fields_typed_1.default.X_CORRELATION_ID, testId).send();
chai_1.assert.isUndefined(correlationIdService_1.correlationIdService.getId());
chai_1.assert.strictEqual(actual, testId, 'getId() should return id from x-correlation-id header of inbound request');
chai_1.assert.strictEqual(actual2, testId, 'getId() should return id from x-correlation-id header of inbound request');
});
it('should maintain correlation id with async/await operations', async () => {
const testId = 'correlation-id-123';
let actual = '';
let actual2 = '';
const app = express();
app.use((0, correlationIdMiddleware_1.createCorrelationIdMiddleware)());
app.get('/', async (req, res, next) => {
try {
actual = correlationIdService_1.correlationIdService.getId();
await delay(250);
actual2 = correlationIdService_1.correlationIdService.getId();
}
catch (e) {
next(e);
}
finally {
res.end();
}
});
chai_1.assert.isUndefined(correlationIdService_1.correlationIdService.getId());
await request(app).get('/').set(http_header_fields_typed_1.default.X_CORRELATION_ID, testId).send();
chai_1.assert.isUndefined(correlationIdService_1.correlationIdService.getId());
chai_1.assert.strictEqual(actual, testId, 'getId() should return id from x-correlation-id header of inbound request');
chai_1.assert.strictEqual(actual2, testId, 'getId() should return id from x-correlation-id header of inbound request');
});
it('should keep correlation ids in nested requests', async () => {
const testId = 'correlation-id-123';
const testId2 = 'correlation-id-456';
let actual = '';
let actual2 = '';
let actual3 = '';
let actual4 = '';
let actual5 = '';
const app = express();
app.use((0, correlationIdMiddleware_1.createCorrelationIdMiddleware)());
app.get('/', async (req, res, next) => {
try {
actual = correlationIdService_1.correlationIdService.getId();
await delay(250);
actual2 = correlationIdService_1.correlationIdService.getId();
await request(app).get('/foo').set(http_header_fields_typed_1.default.X_CORRELATION_ID, testId2).send();
actual3 = correlationIdService_1.correlationIdService.getId();
}
catch (e) {
next(e);
}
finally {
res.end();
}
});
app.get('/foo', async (req, res, next) => {
try {
actual4 = correlationIdService_1.correlationIdService.getId();
await delay(250);
actual5 = correlationIdService_1.correlationIdService.getId();
}
catch (e) {
next(e);
}
finally {
res.end();
}
});
chai_1.assert.isUndefined(correlationIdService_1.correlationIdService.getId());
await request(app).get('/').set(http_header_fields_typed_1.default.X_CORRELATION_ID, testId).send();
chai_1.assert.isUndefined(correlationIdService_1.correlationIdService.getId());
chai_1.assert.strictEqual(actual, testId, 'getId() should return id from x-correlation-id header of inbound request');
chai_1.assert.strictEqual(actual2, testId, 'getId() should return id from x-correlation-id header of inbound request');
chai_1.assert.strictEqual(actual3, testId, 'getId() should return id from x-correlation-id header of inbound request');
chai_1.assert.strictEqual(actual4, testId2, 'getId() should return id from x-correlation-id header of inbound request');
chai_1.assert.strictEqual(actual5, testId2, 'getId() should return id from x-correlation-id header of inbound request');
});
// tslint:disable: no-console
it('should keep correlation ids separated in parallel requests', async function () {
this.timeout(5000);
const testId = 'correlation-id-123';
const testId2 = 'correlation-id-456';
let actual = '';
let actual2 = '';
let actual4 = '';
let actual5 = '';
let unlock;
const lock = new Promise(async (resolve, reject) => {
unlock = resolve;
});
const app = express();
app.use((0, correlationIdMiddleware_1.createCorrelationIdMiddleware)());
app.get('/', async (req, res, next) => {
try {
actual = correlationIdService_1.correlationIdService.getId();
console.log('start of req1', actual);
await lock;
actual2 = correlationIdService_1.correlationIdService.getId();
console.log('end of req1', actual2);
}
catch (e) {
next(e);
}
finally {
res.end();
}
});
app.get('/foo', async (req, res, next) => {
try {
actual4 = correlationIdService_1.correlationIdService.getId();
console.log('start of req2', actual4);
unlock();
await this.timeout(200);
actual5 = correlationIdService_1.correlationIdService.getId();
console.log('end of req2', actual5);
}
catch (e) {
next(e);
}
finally {
res.end();
}
});
console.log('send req1');
chai_1.assert.isUndefined(correlationIdService_1.correlationIdService.getId());
const req1 = request(app).get('/').set(http_header_fields_typed_1.default.X_CORRELATION_ID, testId).send();
console.log('send req2');
chai_1.assert.isUndefined(correlationIdService_1.correlationIdService.getId());
const req2 = request(app)
.get('/foo')
.set(http_header_fields_typed_1.default.X_CORRELATION_ID, testId2)
.send();
await Promise.all([req1, req2]);
chai_1.assert.isUndefined(correlationIdService_1.correlationIdService.getId());
chai_1.assert.strictEqual(actual, testId, 'getId() should return id from x-correlation-id header of inbound request');
chai_1.assert.strictEqual(actual2, testId, 'getId() should return id from x-correlation-id header of inbound request');
chai_1.assert.strictEqual(actual4, testId2, 'getId() should return id from x-correlation-id header of inbound request');
chai_1.assert.strictEqual(actual5, testId2, 'getId() should return id from x-correlation-id header of inbound request');
});
it('should work with operations causing errors', async () => {
const testId = 'correlation-id-123';
let actual = '';
const app = express();
app.use((0, correlationIdMiddleware_1.createCorrelationIdMiddleware)());
app.get('/', (req, res, next) => {
actual = correlationIdService_1.correlationIdService.getId();
throw new Error('some error');
});
chai_1.assert.isUndefined(correlationIdService_1.correlationIdService.getId());
const result = await request(app)
.get('/')
.set(http_header_fields_typed_1.default.X_CORRELATION_ID, testId)
.send();
chai_1.assert.strictEqual(result.status, 500);
chai_1.assert.isUndefined(correlationIdService_1.correlationIdService.getId());
chai_1.assert.strictEqual(actual, testId, 'getId() should return id from x-correlation-id header of inbound request');
});
it('a filter can be specified', async () => {
const testId = 'correlation-id-123';
const filter = (req) => {
if (req.path.startsWith('/ok/')) {
return true;
}
return false;
};
const app = express();
app.use((0, correlationIdMiddleware_1.createCorrelationIdMiddleware)(filter));
app.get('/ok/1', (req, res) => {
const actual = correlationIdService_1.correlationIdService.getId();
chai_1.assert.strictEqual(actual, testId, 'getId() should return id from x-correlation-id header of inbound request');
res.end();
});
app.get('/ok/2', (req, res) => {
const actual = correlationIdService_1.correlationIdService.getId();
chai_1.assert.strictEqual(actual, testId, 'getId() should return id from x-correlation-id header of inbound request');
res.end();
});
app.get('/notok/1', (req, res) => {
const actual = correlationIdService_1.correlationIdService.getId();
chai_1.assert.isUndefined(actual);
res.end();
});
await request(app).get('/ok/1').set(http_header_fields_typed_1.default.X_CORRELATION_ID, testId).send();
await request(app).get('/ok/2').set(http_header_fields_typed_1.default.X_CORRELATION_ID, testId).send();
await request(app).get('/notok/1').set(http_header_fields_typed_1.default.X_CORRELATION_ID, testId).send();
});
it('getCidInfo() cid received', async () => {
const testId = 'correlation-id-123';
const app = express();
app.use((0, correlationIdMiddleware_1.createCorrelationIdMiddleware)());
app.get('/', (req, res) => {
const info = correlationIdService_1.correlationIdService.getCidInfo(req);
chai_1.assert.strictEqual(info.current, testId);
chai_1.assert.strictEqual(info.receivedInRequest, testId);
chai_1.assert.isUndefined(info.generated);
res.end();
});
await request(app).get('/').set(http_header_fields_typed_1.default.X_CORRELATION_ID, testId).send();
});
it('getCidInfo() cid generated', async () => {
const app = express();
app.use((0, correlationIdMiddleware_1.createCorrelationIdMiddleware)());
app.get('/', (req, res) => {
const info = correlationIdService_1.correlationIdService.getCidInfo(req);
chai_1.assert.match(info.current, uuidMatcher);
chai_1.assert.strictEqual(info.current, info.generated);
chai_1.assert.isUndefined(info.receivedInRequest);
res.end();
});
await request(app).get('/').send();
});
});
//# sourceMappingURL=correlationIdMiddleware.test.js.map