aboutsummaryrefslogtreecommitdiffstats
path: root/src/features
diff options
context:
space:
mode:
Diffstat (limited to 'src/features')
-rw-r--r--src/features/messages.js19
1 files changed, 17 insertions, 2 deletions
diff --git a/src/features/messages.js b/src/features/messages.js
index dc311d8..a517407 100644
--- a/src/features/messages.js
+++ b/src/features/messages.js
@@ -726,7 +726,8 @@ export function messagesFeature(ctx) {
// thumbnail is to be had there, so after a second quick refusal the host
// 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
- const NOCORS_KEY = 'coinos-thumb-nocors-v2';
+ // v3: v2 also caught dropped connections (primal again, on a phone)
+ const NOCORS_KEY = 'coinos-thumb-nocors-v3';
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; };
@@ -747,12 +748,26 @@ export function messagesFeature(ctx) {
// the host refused. That wrote primal and coinos.io off as "no CORS" and
// left every picture hosted there painting from the full-size original.
// So a refusal is retried once past the cache before anyone is blamed.
+ // And a refusal looks exactly like a dropped connection (a phone between
+ // networks, a DNS hiccup): both are a quick TypeError. Two of those wrote
+ // blossom.primal.net off for a week on a phone. So the host is only
+ // blamed (TypeError rethrown) when a plain no-cors ask of the same URL
+ // goes through; otherwise it's the network, and the error says so.
async function corsFetch(url, signal) {
try {
return await fetch(url, { mode: 'cors', signal });
} catch (e) {
if (!e || e.name !== 'TypeError') throw e;
- return fetch(url, { mode: 'cors', cache: 'reload', signal });
+ try {
+ return await fetch(url, { mode: 'cors', cache: 'reload', signal });
+ } catch (e2) {
+ 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;
+ const net = new Error('network'); net.name = 'NetworkError';
+ throw net;
+ }
}
}
function makeThumb(pk, p) {