// services/api/src/request-id.middleware.spec.ts —— 请求 ID 解析单测: // 透传上游值 / 缺省生成 UUID / 超长值拒收换新(Task 7 遗留项④)。 import type { ServerResponse } from 'node:http'; import { MAX_REQUEST_ID_LENGTH, resolveRequestId, } from './request-id.middleware'; function fakeReq(header?: string): { headers: Record; id?: string } { return header === undefined ? { headers: {} } : { headers: { 'x-request-id': header } }; } function fakeRes(): ServerResponse & { captured?: string } { const res = { headers: {} } as unknown as ServerResponse & { captured?: string }; Object.defineProperty(res, 'setHeader', { value: (name: string, value: string) => { res.captured = value; return res; }, }); return res; } describe('resolveRequestId', () => { it('echoes a reasonable upstream x-request-id', () => { const req = fakeReq('upstream-id-1'); const res = fakeRes(); expect(resolveRequestId(req as never, res)).toBe('upstream-id-1'); expect(req.id).toBe('upstream-id-1'); expect(res.captured).toBe('upstream-id-1'); }); it('generates a UUID v4 when the header is absent', () => { const req = fakeReq(); const id = resolveRequestId(req as never, fakeRes()); expect(id).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/); expect(req.id).toBe(id); }); it('treats a blank header as absent', () => { const id = resolveRequestId(fakeReq(' ') as never, fakeRes()); expect(id).not.toBe(' '); }); it('replaces an over-long upstream id (>128 chars) with a fresh UUID', () => { const overlong = 'x'.repeat(MAX_REQUEST_ID_LENGTH + 1); const req = fakeReq(overlong); const res = fakeRes(); const id = resolveRequestId(req as never, res); expect(id).not.toBe(overlong); expect(id.length).toBeLessThanOrEqual(MAX_REQUEST_ID_LENGTH); expect(req.id).toBe(id); expect(res.captured).toBe(id); }); it('still echoes an id of exactly the cap (128 chars)', () => { const exact = 'y'.repeat(MAX_REQUEST_ID_LENGTH); const id = resolveRequestId(fakeReq(exact) as never, fakeRes()); expect(id).toBe(exact); }); it('reuses req.id when already resolved (pino-http genReqId runs first)', () => { const req = { ...fakeReq('ignored'), id: 'already-set' }; expect(resolveRequestId(req as never, fakeRes())).toBe('already-set'); }); });