Commit c5eb62c
fix(net): make fetch behave like native fetch (#1652)
* fix(net): make fetch behave like native fetch
@cacheable/net previously threw `Error("Fetch failed with status …")` on any
non-2xx response, which diverged from native `fetch` semantics. Callers written
for `fetch` check `response.ok`, but that became unreachable dead code because the
request already rejected, producing cryptic errors on non-2xx (e.g. routing a
subscription POST through the client).
Align with native `fetch`:
- Resolve with the Response for any completed exchange (4xx/5xx included); only
reject on real network errors. Removes all four throw sites.
- Only cache storable responses: simple mode caches 2xx only; HTTP-cache mode
continues to defer to RFC 7234 `storable()`. Errors are returned, never cached.
- Make `options` optional so `fetch(url)` works, matching `fetch(input, init?)`
and the documented signature.
- Preserve `response.url` (plus `redirected`/`type` from live responses) on
reconstructed/cached responses via a shared `makeResponse` helper, so the final
URL survives caching and the get/post/etc. helpers.
Add deterministic local-server tests covering non-2xx across every path (no
cache, simple cache, HTTP cache, POST/HEAD, helpers, CacheableNet), error
responses not being cached, optionless `fetch(url)`, and url/redirected
preservation. Document the native-fetch error semantics in the README.
https://claude.ai/code/session_01QeG7AkCcuwmpw9JJSX26zi
* fix(net): address review — no error caching, coalescing, 304 + cached-redirect metadata
Resolves four issues raised in review of the native-fetch alignment:
- Don't cache HTTP errors under default cache semantics. Non-2xx responses now
return early before policy creation, so statuses RFC 7234 deems storable
(404/410/501/…) are no longer served from cache — matching the documented
"errors are never cached" contract.
- Fix a 304/null-body throw. Reconstructing `new Response("", { status: 304 })`
threw, so conditional GETs (and 204s) still rejected. makeResponse now coerces
the body to null for null-body statuses (101/103/204/205/304).
- Restore stampede protection in simple-cache mode. The get+fetch+set rewrite
dropped getOrSet's coalescing; concurrent misses now share a single origin
request via coalesceAsync, while each caller rebuilds its own Response (so the
body stays independently readable) and errors remain uncached.
- Persist final-URL metadata for cached responses. CachedResponse now stores
url/redirected/type so cache hits report the same final URL (after redirects)
as the original miss, instead of falling back to the request URL.
Adds local-server tests for each (304 helper, concurrent-miss coalescing,
cached-redirect metadata, and request-url fallback for legacy entries) and
updates the README error-handling note. Adds @cacheable/utils dependency for
coalesceAsync.
https://claude.ai/code/session_01QeG7AkCcuwmpw9JJSX26zi
* docs(net): describe native fetch semantics in README features
Update the lead feature bullet, which still described fetch as coming from
undici with caching always on. Reflect the current behavior: a drop-in fetch
built on the runtime's global fetch that resolves on any status (check
response.ok), preserves response.url/redirected/type, with caching opt-in.
https://claude.ai/code/session_01QeG7AkCcuwmpw9JJSX26zi
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent ee73e5a commit c5eb62c
7 files changed
Lines changed: 641 additions & 117 deletions
File tree
- packages/net
- src
- test
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
13 | | - | |
| 13 | + | |
| 14 | + | |
14 | 15 | | |
15 | 16 | | |
16 | 17 | | |
| |||
119 | 120 | | |
120 | 121 | | |
121 | 122 | | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
122 | 146 | | |
123 | 147 | | |
124 | 148 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
40 | 40 | | |
41 | 41 | | |
42 | 42 | | |
| 43 | + | |
43 | 44 | | |
44 | 45 | | |
45 | 46 | | |
| |||
0 commit comments