import { createMiddleware } from "hono/factory"; import type { AppEnv } from "@/worker/types"; import { createLogger, errorContext } from "@/worker/util/logging"; import { destinationHost, pathPrefix } from "@/worker/util/request-context"; const log = createLogger("request"); function overwriteHeader(value: string | undefined): string | null { if (!value) return null; return value.toUpperCase() === "F" ? "F" : "T"; } export const requestLogging = () => createMiddleware(async (c, next) => { const started = Date.now(); const request = c.req.raw; const url = new URL(c.req.url); const base = { requestId: c.get("requestId"), method: c.req.method, pathPrefix: pathPrefix(url.pathname), hostLabel: c.get("hostInfo")?.hostLabel ?? null, davDepth: request.headers.get("depth"), davDestinationHost: destinationHost(request), davOverwrite: overwriteHeader(c.req.header("overwrite")), davIfPresent: request.headers.has("if"), litmusHeader: c.req.header("x-litmus") ?? null, }; try { await next(); log.info("request.complete", { ...base, status: c.res.status, latencyMs: Date.now() - started, errorCode: c.res.status >= 400 ? `http_${c.res.status}` : null, }); } catch (error) { log.error("request.error", { ...base, status: 500, latencyMs: Date.now() - started, errorCode: "unhandled_exception", ...errorContext(error), }); throw error; } });