diff --git a/api/_common/upstream.js b/api/_common/upstream.js index 52a333e..60245fb 100644 --- a/api/_common/upstream.js +++ b/api/_common/upstream.js @@ -2,8 +2,7 @@ export const upstreamError = (error, context = 'Lookup') => { const status = error.response?.status; if (status === 404 || status === 410) return { skipped: `No ${context} data for this host` }; - if (status === 401 || status === 403) - return { error: `${context} authentication failed (check API key)` }; + if (status === 401 || status === 403) return { error: `${context} blocked (HTTP ${status})` }; if (status === 429) return { error: `${context} rate-limited by upstream` }; if (status && status >= 500) return { error: `${context} upstream is unavailable` }; if (error.code === 'ECONNABORTED') return { error: `${context} timed out` }; diff --git a/api/screenshot.js b/api/screenshot.js index 441eb5d..725841b 100644 --- a/api/screenshot.js +++ b/api/screenshot.js @@ -84,6 +84,9 @@ const screenshotHandler = async (targetUrl) => { try { return { image: await puppeteerScreenshot(targetUrl) }; } catch (error) { + if (/ENOENT|Browser was not found|Could not find Chromium/i.test(error.message)) { + return { skipped: error.message }; + } log.error(`puppeteer screenshot failed: ${error.message}`); throw error; } diff --git a/api/tech-stack.js b/api/tech-stack.js index baa2ab2..2d62eff 100644 --- a/api/tech-stack.js +++ b/api/tech-stack.js @@ -34,6 +34,9 @@ const techStackHandler = async (url) => { } return results; } catch (error) { + if (/ENOENT|Browser was not found|Could not find Chromium/i.test(error.message)) { + return { skipped: error.message }; + } throw new Error(error.message); } finally { await wappalyzer.destroy(); diff --git a/src/web-check-live/utils/parse-json.ts b/src/web-check-live/utils/parse-json.ts index f1a4181..f8d879c 100644 --- a/src/web-check-live/utils/parse-json.ts +++ b/src/web-check-live/utils/parse-json.ts @@ -1,16 +1,27 @@ -const FRIENDLY = 'API request failed. This may be a server error, timeout, or platform limitation.'; +const STATUS_MESSAGES: Record = { + 408: 'Request timed out', + 429: 'Rate limited, try again later', + 500: 'Internal server error', + 502: 'Bad gateway, upstream server failed', + 503: 'Service temporarily unavailable', + 504: 'Gateway timed out', +}; + +const FALLBACK = 'API request failed. This may be a server error, timeout, or platform limitation.'; // Decode a fetch Response as JSON, returning a structured error on failure export const parseJson = async (res: Response): Promise => { try { const json = await res.json(); if (!res.ok && !json?.error) { - return { error: json?.errorMessage || json?.message || `${FRIENDLY} (HTTP ${res.status})` }; + const detail = json?.errorMessage || json?.message; + const statusMsg = STATUS_MESSAGES[res.status] || `${FALLBACK} (HTTP ${res.status})`; + return { error: detail ? `${statusMsg} - ${detail}` : statusMsg }; } return json; } catch { - const status = res.status ? ` (HTTP ${res.status})` : ''; - return { error: `API responded with ${status}. ${FRIENDLY}` }; + const statusMsg = STATUS_MESSAGES[res.status] || FALLBACK; + return { error: `${statusMsg} (HTTP ${res.status})` }; } };