Skip to content

Învelișul aplicației se cere de la o adresă pe care nicio pagină nu o are

Vitalie requested to merge 26_app-shell-address into main

Rendererul construia fiecare pagină pornind de la învelișul cerut de la nginx-ul frontendului, iar adresa cerută era /index.html — exact adresa pe care o poate tasta un vizitator. Asta le făcea indistincte: regula scrisă pentru vizitator i s-a răspuns și rendererului. Redirectul livrat prin !45 (merged) a fost urmat de renderer, care a primit pagina pe care tocmai o construia și a injectat în ea; producția a măsurat 799.522 de octeți de HTML per vizitator și 146 de etichete canonical într-o oră, iar schimbarea a fost anulată prin !50 (merged).

Ce se schimbă

  • getShell cere /app-shell.html. nginx răspunde acolo cu același fișier, cu X-Robots-Tag: noindex, nofollow, iar nimic nu redirectează spre acea adresă.
  • /index.html întoarce 301 către /, cu query string-ul păstrat.
  • Cele două reguli error_page 404 trec pe adresa rendererului. error_page <cod> <uri> e un redirect intern: reia potrivirea de locații, deci un corp de 404 care numea /index.html ar fi primit redirectul de mai sus și orice adresă inexistentă ar fi sărit pe prima pagină.
  • Plasă de siguranță independentă de nginx: getShell refuză un document care poartă un rel="canonical" sau blocul id="seo-content" — ambele scrise doar de renderer — și refuză înainte de scrierea în cache, deci o greșeală costă o cerere, nu un minut de cereri.
  • Redirectele nu se mai urmăresc la cererea artefactelor de build (redirect: 'manual'). Urmărirea lor e cauza de transport a incidentului.

Verificare

Configurația a fost exercitată într-un container nginx 1.27 cu fișierul din acest MR și cu build-ul real, plus backendul pornit alături:

Adresă Rezultat
/index.html 301 -> /
/index.html?utm_source=fb&a=1 301 -> /?utm_source=fb&a=1
/app-shell.html 200, învelișul brut, zero canonical, X-Robots-Tag: noindex, nofollow
/admin 200, X-Robots-Tag: noindex, nofollow
/pagina-care-nu-exista 404, nu redirect
/en/index.html 404
/ 200, 10.400 de octeți, un canonical, un <noscript>, titlul în română

Contra-proba care lipsea data trecută: pagina de start măsurată după schimbare are un singur canonical și 10 KB, nu 146 și 800 KB. Cu rendererul oprit, / cade pe învelișul static (4.431 de octeți) și adresa inexistentă rămâne 404.

Backend: 609 teste în 40 de fișiere, toate trec. Frontend: 441 de teste în 33 de fișiere, tsc --noEmit -p tsconfig.app.json curat, oxlint cu singurul avertisment preexistent din src/App.tsx.

Ordinea la deploy

Ambele imagini poartă eticheta commit-ului, deci ambele containere se recreează la fiecare deploy, iar frontendul pornește doar după ce backendul e sănătos. Direcția care ar imbrica paginile — backend vechi cu frontend nou — nu poate apărea. Direcția inversă degradează la învelișul static. De aceea getShell nu primește o cale de rezervă spre /index.html: nu ajută direcția care se strică și ar reintroduce chiar amplificatorul din incident.

Efect secundar de reținut

Corpurile de 404 trec acum prin locația învelișului, deci orice 404 poartă X-Robots-Tag: noindex, nofollow. Corect pentru un 404, dar e o schimbare, nu un lucru neutru.

Rămân nebifate ultimele două puncte ale issue-ului: blocul robots.txt inserat de Cloudflare și decizia despre roboții de AI sunt setări de zonă și o decizie de produs, nu se fac din repo.

See #26 (closed)

Merge request reports