diff --git a/api/src/routes/dot-lookup.ts b/api/src/routes/dot-lookup.ts index a55dda1..7078ad4 100644 --- a/api/src/routes/dot-lookup.ts +++ b/api/src/routes/dot-lookup.ts @@ -20,15 +20,19 @@ const FMCSA_BASE = "https://mobile.fmcsa.dot.gov/qc/services/carriers"; async function fmcsaFetch(path: string): Promise { if (!FMCSA_API_KEY) return null; + const controller = new AbortController(); + const timer = setTimeout(() => controller.abort(), 5000); try { const url = `${FMCSA_BASE}/${path}${path.includes("?") ? "&" : "?"}webKey=${FMCSA_API_KEY}`; const resp = await fetch(url, { - signal: AbortSignal.timeout(5000), + signal: controller.signal, headers: { "Accept": "application/json" }, }); + clearTimeout(timer); if (!resp.ok) return null; return await resp.json(); } catch { + clearTimeout(timer); return null; } } @@ -515,7 +519,7 @@ router.get("/api/v1/dot/lookup", async (req, res) => { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ entity_name: name, state_code: state }), - signal: AbortSignal.timeout(5000), + signal: (() => { const c = new AbortController(); setTimeout(() => c.abort(), 5000); return c.signal; })(), }); if (sosResp.ok) { sosStatus = (await sosResp.json()) as { found?: boolean; status?: string; error?: string }; @@ -593,6 +597,7 @@ router.get("/api/v1/dot/lookup", async (req, res) => { const redCount = checks.filter(c => c.status === "red").length; const yellowCount = checks.filter(c => c.status === "yellow").length; + if (res.headersSent) return; // deadline already responded res.json({ dot_number: rawDot, legal_name: name, @@ -722,7 +727,7 @@ router.post("/api/v1/dot/name-check", async (req, res) => { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ entity_name: name, state_code: stateCode }), - signal: AbortSignal.timeout(5000), + signal: (() => { const c = new AbortController(); setTimeout(() => c.abort(), 5000); return c.signal; })(), }).then(r => r.json()) : Promise.resolve({ skipped: true }),