La mise en cache retombait sur le relais dès que la tentative directe n'était
pas « ok », sans distinguer « je n'ai pas pu demander » de « on m'a répondu
qu'il n'y a rien ». Un 404 est une réponse : le relais irait chercher la même
URL et ne peut pas faire mieux.
D'où deux 404 par vignette manquante sur la bibliographie d'un auteur, à
chaque affichage puisque rien ne se met alors en cache — et dont le second
venait de notre propre serveur, qui refuse par construction une URL absente
de la base.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Le cache hors-ligne des couvertures ne marchait que pour OpenLibrary : il lit
les octets par fetch(), donc exige un en-tête CORS, alors que le formulaire
livre accepte n'importe quelle URL. Ces images s'affichaient (une <img> n'a
que faire du CORS) sans jamais pouvoir être rangées — et le fetch repartait à
chaque affichage puisque rien n'était stocké.
GET /api/couvertures relaie l'image depuis notre serveur. Un proxy est une
surface SSRF : il est borné par deux verrous indépendants — l'URL doit déjà
exister en base comme couverture, et la connexion ne s'ouvre que vers une
adresse publiquement routable. Ce second verrou vit dans le ConnectCallback,
pas dans une pré-vérification DNS, ce qui ferme aussi le DNS rebinding — et
c'est ce qui permet de suivre les redirections, indispensables puisque
covers.openlibrary.org répond 302.
Tout refus répond 404 : distinguer les cas ferait du point d'entrée un oracle
sur les URL connues et sur le réseau du serveur.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- A1 : forcer la revalidation HTTP (Cache-Control: no-cache) sur les fichiers statiques,
pour empêcher un navigateur de garder indéfiniment un CSS/JS périmé quand le service
worker ne s'active pas.
- A2 : le filtre du catalogue (statut, type de document) reprend les mêmes pastilles
colorées que les cartes (Libelles.ClasseStatut / nouvelle Libelles.ClasseTypeDocument).
- A3 : remplacement du logo par défaut de Blazor par un pictogramme de livre ouvert
(favicon, icônes PWA, logo du bandeau, logo mabibli_ynh).
- A4 : une couverture cassée désactive aussi son bouton d'agrandissement.
- A5 : cache IndexedDB des couvertures pour la consultation hors-ligne, sans ralentir
l'affichage en ligne (mise en cache en tâche de fond). L'allègement (redimensionnement,
WebP) reste hors scope, à mesurer avant de s'y engager.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Le piege que CLAUDE.md signale : en Blazor WebAssembly le code tourne dans le
navigateur alors que SQLite vit sur le serveur, et le service worker ne met en
cache que les assets. Sans travail explicite, l'application demarre hors-ligne
et affiche une bibliotheque vide.
- js/cache-hors-ligne.js : instantanes JSON dans IndexedDB, et surveillance des
bascules online/offline. Aucune logique metier.
- CacheHorsLigne / EtatReseau : lecture-ecriture des instantanes, et etat reseau
combinant navigator.onLine (fiable seulement par sa negation) avec le sort
reel des appels HTTP.
- ServiceLivresApi : les lectures retombent sur le cache, les ecritures sont
refusees. Le catalogue entier est memorise, pas les reponses filtrees : c'est
ce qui rend la recherche hors-ligne possible sur tout le fonds.
- FiltreLivresLocal : pendant navigateur de FiltreLivres, avec un test qui
confronte les deux implementations sur les memes donnees.
- Interface : pastille et bandeau d'etat avec la date de synchronisation, et
actions d'ecriture desactivees avec leur raison plutot que boutons morts.
- js/mise-a-jour.js : les empreintes WASM etant desactivees, le service worker
est le seul cache-busting du projet. L'enregistrement journalise desormais ses
echecs, et un bandeau propose la nouvelle version sans attendre la fermeture
de tous les onglets.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>