| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
|
|
| import { AsyncLocalStorage } from "node:async_hooks";
|
| import { randomUUID } from "crypto";
|
|
|
| type HeaderReader = {
|
| get?: (name: string) => string | null | undefined;
|
| };
|
|
|
| type RequestLike = {
|
| headers?: HeaderReader | null;
|
| } | null;
|
|
|
| const requestIdStore = new AsyncLocalStorage<string>();
|
|
|
| function getHeaderValue(request: RequestLike, name: string): string | null {
|
| const value = request?.headers?.get?.(name);
|
| return typeof value === "string" && value.length > 0 ? value : null;
|
| }
|
|
|
| |
| |
| |
| |
| |
|
|
| export function getRequestId() {
|
| return requestIdStore.getStore() || null;
|
| }
|
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| export async function withRequestId<T>(
|
| request: RequestLike,
|
| handler: () => T | Promise<T>
|
| ): Promise<T> {
|
| const existingId = getHeaderValue(request, "x-request-id");
|
| const requestId = existingId || randomUUID();
|
| return requestIdStore.run(requestId, handler);
|
| }
|
|
|
| |
| |
| |
| |
| |
| |
|
|
| export function addRequestIdHeader(headers: Record<string, string> = {}): Record<string, string> {
|
| const requestId = getRequestId();
|
| if (requestId) {
|
| return { ...headers, "x-request-id": requestId };
|
| }
|
| return headers;
|
| }
|
|
|
| |
| |
| |
| |
| |
| |
| |
|
|
| export function attachRequestIdToResponse(request: RequestLike, response: Response): Response {
|
| const requestId = getRequestId() || getHeaderValue(request, "x-request-id") || randomUUID();
|
|
|
| const headers = new Headers(response.headers);
|
| headers.set("x-request-id", requestId);
|
|
|
| return new Response(response.body, {
|
| status: response.status,
|
| statusText: response.statusText,
|
| headers,
|
| });
|
| }
|
|
|
| |
| |
| |
|
|
| export function generateRequestId() {
|
| return randomUUID();
|
| }
|
|
|