8 min read

Eye Training · fetch and the Network

A network call can fail, be slow, succeed with an error status, run twice, or go somewhere you didn't mean. Check each one.

Part 2 · Surface 16. Bug counts are hidden and some snippets are clean. See Start Here for how to use these drills.


J · The basics

Bug hunt
J · Get a user
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
J · Place an order
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
J · Search
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
J · Create an order
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min

M · Three years in, these should jump out

Bug hunt
M · Exchange rates
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
M · Delete an item
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
M · Error messages
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
M · Pay with retries
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 2 min
Bug hunt
M · Rate-limited API
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
M · Download a report
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min

S · Where seniors stand out

Bug hunt
S · Timeout, take two
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 2 min
Bug hunt
S · Avatar proxy
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
S · CORS middleware
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
S · Webhook sender
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 2 min

What your eye checks

Whenever you see fetch (or any HTTP client), ask:

  1. Is res.ok checked before the body is read? fetch resolves on 404 and 500.
  2. What if it never answers? Is there a timeout, and does it cover the body?
  3. What if it rejects? Network errors take a different path from error statuses. Are both handled?
  4. Is the request built safely? Query values encoded, body serialised, Content-Type set, credentials in headers, not URLs.
  5. Is the response what you assume? A 204 has no body; an error body may be HTML.
  6. Is it safe to retry? Only idempotent calls, or with an idempotency key. Only retryable failures, with backoff and jitter, respecting Retry-After.
  7. Where does the URL come from? A user-supplied URL fetched by the server is SSRF.
  8. Server side: who may call this from a browser? CORS with credentials needs an allowlist.

Tells

You seeAsk
await fetch(…) then res.json()Where's the res.ok check?
fetch(url) with no signal on a serverHow long can it hang?
body: {Serialised? Content-Type?
${value} inside a query stringEncoded?
?token= / ?apiKey=Who logs this URL?
A retry loop around a POSTIdempotency key? Which failures?
status === 429Is Retry-After read?
clearTimeout right after await fetchWhat about the body?
fetch(req.query.url) / fetch(req.body.url)Which hosts can it reach?
Allow-Origin set from req.headers.originIs there an allowlist?
if (!res.ok) as the only failure pathWhat if fetch rejects?

Go deeper