Skip to content

Record request URL and HTTP status on failed downloads - #77

Merged
jonocodes merged 2 commits into
mainfrom
feature/proxy-failure-context
Oct 3, 2026
Merged

jonocodes merged 2 commits into
mainfrom
feature/proxy-failure-context

Conversation

@jonocodes

@jonocodes jonocodes commented Oct 2, 2026 •

Copy link
Copy Markdown
Owner

Why

While testing the app log (#70), a failed save only recorded:

Failed to download article {"url":"https://github.com/...","error":"NetworkError when attempting to fetch resource."}

That's not enough to act on. The underlying reason is a browser security boundary: when a cross-origin response fails the CORS check (no Access-Control-Allow-Origin), the browser filters the response before JS sees it. fetch rejects with a bare TypeError, and there is no response object — so status, headers, and body are all unavailable. XMLHttpRequest, no-cors fetches, and PerformanceResourceTiming.responseStatus all report 0 for such responses. The status is only readable when the response carries CORS headers.

What

Generic failure context on downloads — no CORS-specific logic:

  • fetchWithTimeout throws a FetchError carrying the resolved requestUrl (proxy included) and the HTTP status when the browser exposed one (src/utils/article/tools.ts).
  • ingestUrl logs requestUrl and status on failure; image-download failures carry the same.
  • When the response is CORS-filtered and no status is available, the log still names the exact request URL so it can be opened directly (or seen in devtools).

A failed save now logs:

{
  "url": "https://github.com/...",
  "error": "Network error: NetworkError when attempting to fetch resource.",
  "requestUrl": "https://lively-cors-proxy-....workers.dev/?url=..."
}

and, when the proxy returns an error with CORS headers:

{
  "url": "https://github.com/...",
  "error": "HTTP 429 Too Many Requests",
  "requestUrl": "https://lively-cors-proxy-....workers.dev/?url=...",
  "status": 429
}

Testing

  • npx tsc --noEmit — clean
  • npx jest — 307 passed
  • npm run lint — no new warnings

Base of this PR is main; the app-log feature it builds on (#70) is already merged. CHANGELOG updated.

A cross-origin response without CORS headers (e.g. a 429 from the proxy)
makes fetch reject with a bare TypeError and hides the HTTP status from JS.
Capture the resolved request URL and any exposed status in FetchError, and
when the status is hidden and a proxy was used, probe reachability to tell
'reachable but blocked' apart from 'unreachable', plus an actionable hint.
@netlify

netlify Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for savrlist ready!

Name Link
🔨 Latest commit 69cfecc
🔍 Latest deploy log https://app.netlify.com/projects/savrlist/deploys/6ac0403f28fc2d00083c60e2
😎 Deploy Preview https://deploy-preview-77--savrlist.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@jonocodes jonocodes changed the title Surface CORS proxy URL and status in failed-download logs Record request URL and HTTP status on failed downloads Oct 2, 2026
@jonocodes
jonocodes merged commit 3943245 into main Oct 3, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant