Fiecare cerere către API plătește un drum în plus: preflight CORS necache-uit
Frontendul și API-ul sunt pe domenii diferite, deci browserul cere întâi permisiunea (OPTIONS) și abia apoi datele. Răspunsul la acea permisiune nu spune cât timp e valabil, așa că browserul îl reface mereu. Pe o conexiune mobilă din Moldova fiecare drum costă zeci sau sute de milisecunde, plătite înaintea fiecărei cereri.
Ce am găsit
Măsurat pe producție, în raportul Lighthouse al paginii de start, cererea care decide când apare imaginea principală:
985 -> 1128 0 B OPTIONS https://api.hyperice.md/api/banners?locale=ro
1128 -> 1262 1670 B GET https://api.hyperice.md/api/banners?locale=ro
143 ms doar ca să afle că are voie. Antetul lipsește:
$ curl -s -X OPTIONS "https://api.hyperice.md/api/banners?locale=ro" \
-H "Origin: https://hyperice.md" -H "Access-Control-Request-Method: GET" -D - -o /dev/null
HTTP/2 204
access-control-allow-origin: https://hyperice.md
access-control-allow-credentials: true
access-control-allow-methods: GET,HEAD,PUT,PATCH,POST,DELETE
access-control-allow-headers: content-type
Niciun Access-Control-Max-Age, deci browserul folosește implicitul lui (5 secunde în Chrome) și reia întrebarea. backend/src/app.ts:31 configurează cors({ origin: CORS_ORIGIN, credentials: true }) fără maxAge.
Se vede și în numărătoarea de resurse: 22 de intrări către API pe pagina de start, adică 11 cereri și 11 permisiuni.
De făcut
-
maxAgepe configurațiacorsdinbackend/src/app.ts:31, ca permisiunea să fie ținută minte de browser -
Verifică de ce cererile publice de citire declanșează preflight: un GETfără antete proprii e o cerere simplă, care nu are nevoie de permisiune deloc. DacăContent-Typesaucredentialsse trimit și pe rutele publice dinfrontend/src/lib/api.ts, drumul dispare complet pentru ele -
Sesiunea de administrare rămâne pe cookie: rutele de panou au nevoie în continuare de cereri cu credențiale
Criteriu de acceptare
Pe încărcare completă a paginii de start, măsurat pe producție: numărul de intrări OPTIONS către API scade la cel mult una, iar cererea /api/banners pornește fără drum de permisiune înaintea ei.