When many customers order at the same time, their log lines get mixed together. When one of them writes that their order went wrong, you can't tell which lines are theirs. The fix is a request ID: a random name made for each request, sent back with the answer in a header and written in every log line about that request. The customer gives you the id, and you search the log for it.
Express can run code before every route. A middleware is a function you give to app.use: Express calls it at the start of every request, before the routes below it. It gets req: Request and res: Response like a route, plus next: NextFunction: calling next() tells Express to go on to the route. Values that belong to the request being handled go on req: each request gets its own. TypeScript only lets you use the properties a type has, so a declare global line adds the new property to Express's Request type. For example, to remember when each request started:
declare global { namespace Express { interface Request { started: number } } }
app.use((req: Request, res: Response, next: NextFunction) => {
req.started = Date.now();
next();
});
The route that handles the request can read req.started later. A middleware can also set a header with res.set(name, value): the header waits in res and leaves with whatever answer is sent. For the id itself, crypto.randomUUID() makes 36 random characters, the digits 0–9 and the letters a–f in five groups with dashes between them, practically never the same twice. A test can't know a random id in advance, so it checks a part: text.includes(part) is true when part is found inside text, and assert.ok(value) passes when the value is true.
The check sends four requests. The ids are random, so it shows them as <id 1>, <id 2> and so on:
POST /orders {"product_id": 1, "quantity": 2} → 201 | X-Request-Id: <id 1>
log: [<id 1>] Order placed: 2 x Mug, total 24
POST /orders {"product_id": 3, "quantity": 1} → 201 | X-Request-Id: <id 2>
log: [<id 2>] Order placed: 1 x Lamp, total 29
POST /orders {"product_id": 99, "quantity": 1} → 404 | X-Request-Id: <id 3>
GET /about → 404 | X-Request-Id: <id 4>
Your task: in a middleware, make an id for every request, keep it in req.requestId and send it back in the X-Request-Id header. Then write the id in square brackets at the start of the order's log line. Last, write the test "log has request id", which checks that the header's id is in the logged line. The check runs it on the shop, where it must pass, and on two broken copies, one that leaves the id out of the log and one that makes a second id for the answer, where it must fail.
Assignment
Follow the Coding Tutorial to give every request an id, put it in the answer's header and in the order's log line, and test that the two match.
Hint
The declare global line at the top already gives Request its requestId: string, so the route can read req.requestId. Don't leave out next(). In the test, give the function the parameter t for t.mock.method, and keep the answer of the post in response: in response.headers the names are in lowercase, so the id is response.headers["x-request-id"].
Free plan: 30 tutor messages. PRO is unlimited.
