aboutsummaryrefslogtreecommitdiffstats
path: root/src/features/messages.js
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-10-03 22:43:54 -0700
committerAdam Soltys <[email protected]>2026-10-03 22:43:54 -0700
commitf1a0951fd14879abb80db688ac22ea9855bad04a (patch)
tree5cc2bfce69336cbe697926da3ece0f332b167201 /src/features/messages.js
parentdf1d69cf3caa332e6daf68c924a07043bf370942 (diff)
downloadcoinosv3-f1a0951fd14879abb80db688ac22ea9855bad04a.tar.gz
coinosv3-f1a0951fd14879abb80db688ac22ea9855bad04a.zip
CORS write-off only on a refusal corsFetch confirmed, not a body cut off mid-download
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_011bvzKaZosXGHkigcGcSzAR
Diffstat (limited to 'src/features/messages.js')
-rw-r--r--src/features/messages.js12
1 files changed, 6 insertions, 6 deletions
diff --git a/src/features/messages.js b/src/features/messages.js
index a517407..c1e39d7 100644
--- a/src/features/messages.js
+++ b/src/features/messages.js
@@ -727,7 +727,7 @@ export function messagesFeature(ctx) {
// is left alone for a week rather than asked about every new face.
// v2: the first list was mostly wrong (primal's CDN, coinos.io) — see corsFetch
// v3: v2 also caught dropped connections (primal again, on a phone)
- const NOCORS_KEY = 'coinos-thumb-nocors-v3';
+ const NOCORS_KEY = 'coinos-thumb-nocors-v4';
const NOCORS_MS = 7 * 24 * 3600_000;
let noCors = null; // host -> { n, until }
const noCorsNow = () => { if (!noCors) { try { noCors = JSON.parse(localStorage.getItem(NOCORS_KEY) || '{}'); } catch { noCors = {}; } } return noCors; };
@@ -764,7 +764,7 @@ export function messagesFeature(ctx) {
if (!e2 || e2.name !== 'TypeError') throw e2;
let reachable = false;
try { await fetch(url, { mode: 'no-cors', signal }); reachable = true; } catch {}
- if (reachable) throw e2;
+ if (reachable) { e2.corsRefused = true; throw e2; }
const net = new Error('network'); net.name = 'NetworkError';
throw net;
}
@@ -844,7 +844,9 @@ export function messagesFeature(ctx) {
done({ thumb: data, thumbFor: url, thumbPx: THUMB_PX });
} catch (e) {
// a quick TypeError is the CORS refusal (a dead host takes longer)
- if (e && e.name === 'TypeError' && Date.now() - t0 < 4000) noteNoCors(url);
+ // only a refusal corsFetch confirmed (a body cut off mid-download
+ // is a TypeError too)
+ if (e && e.corsRefused) noteNoCors(url);
failed();
} finally { try { bmp && bmp.close(); } catch {} }
})();
@@ -5384,15 +5386,13 @@ export function messagesFeature(ctx) {
}
async function makeMediaThumb(url) {
if (noCorsHost(url) || typeof createImageBitmap === 'undefined' || typeof OffscreenCanvas === 'undefined') return null;
- const t0 = Date.now();
let blob;
try {
const res = await corsFetch(url, AbortSignal.timeout(READY_MS));
if (!res.ok) return null;
blob = await res.blob();
} catch (e) {
- // a quick TypeError is the CORS refusal (a dead host takes longer)
- if (e && e.name === 'TypeError' && Date.now() - t0 < 4000) noteNoCors(url);
+ if (e && e.corsRefused) noteNoCors(url); // refused, as corsFetch confirmed
return null;
}
let bmp;