Blog ·
O insignă care punea cookie pe orice pagină
O imagine din subsol costa douăzeci și două de puncte Lighthouse pe tot site-ul. Reparația nu a fost scoaterea ei, ci ce refuză un proxy.
De Provibr
Scorul de bune practici al site-ului nostru de marketing era 78 pe fiecare pagină. Nu pe o pagină, pe fiecare: pagina principală, pagina de prețuri, documentația, tot, uniform. Scorurile uniforme sunt un semn bun, fiindcă înseamnă că pricina se află în ceva ce împart toate paginile.
Era o singură etichetă de imagine din subsol. O insignă de listare a lansării, încărcată direct de la platforma care o emite, fiindcă așa se cuvine să fie încorporată o astfel de insignă și fiindcă numărul de pe ea se presupune că este viu.
Ce poate face o etichetă de imagine
Insigna este servită de pe o gazdă de API care stă în spatele Cloudflare, iar Cloudflare răspunde cererilor cu cookie-ul lui de administrare a boților: __cf_bm, SameSite=None, Secure, cu domeniul emitentului insignei ca sferă. Aceasta nu este o hotărâre a site-ului a cărui insignă este. Este ce face un CDN, pe un SVG, la fiecare încărcare de pagină, pentru fiecare vizitator.
Două audituri Lighthouse reacționează la asta. Auditul cookie-urilor de la terți cântărește cinci din cele douăzeci și opt de ponderi ale categoriei, iar o problemă de inspector cântărește unu. Șase ponderi pierdute pe o imagine. Peste cele treizeci și opt de măsurători ale rundei anterioare, aceea era toată distanța dintre 78 și 100.
A treia urmare este cea pe care niciun scor nu o surprinde. Adresa IP a fiecărui vizitator pleca spre o firmă cu care el nu alesese să vorbească, pe fiecare pagină, în schimbul unui număr dintr-un subsol.
Nici scoaterea ei nu este răspunsul
Consemnaserăm deja compromisul, într-un comentariu, cu luni în urmă: dacă vreți vreodată asta fără un banner de consimțământ, găzduirea proprie a SVG-ului este calea. Cu contraargumentul atașat, anume că o copie găzduită de noi este o fotografie. Insigna există ca să arate o listare vie; înghețați octeții și rămâneți cu o poză a unei listări.
Există o a treia cale și devine evidentă abia după ce despărțiți două lucruri pe care browserul le face deodată. Browserul aduce octeți și browserul face o conexiune. Numai al doilea este problema.
Așa că insigna vine acum de la originea noastră, la o cale de pe propriul nostru API, iar acea rută aduce sursa din amonte pe server. Aceiași octeți. Browserul vizitatorului face o singură cerere, către noi. Nu există nimic pe fir pe care să se pună un cookie, fiindcă nu există niciun terț în pagina vizitatorului. Iar numărul rămâne viu, fiindcă noi tot întrebăm.
Bunele practici au urcat de la 78 la 100 pe treizeci și două din treizeci și șase de măsurători. Cele patru rămase sunt paginile de articole, care stau la 96 din pricina unui buton de la un terț cu totul diferit, iar aceea este o hotărâre separată și nu o rămășiță.
Ce datorează un proxy celui pentru care face proxy
A servi octeții altcuiva de la propria origine schimbă ce sunt ei. Un SVG încărcat printr-o etichetă de imagine nu poate executa script; aceasta este o garanție de specificație și este una bună. Dar din clipa în care acei octeți vin de pe domeniul nostru, ce se află în ei este al nostru.
Așa că ruta verifică răspunsul înainte să îl dea mai departe. Verificarea aceea nu este dinadins un igienizator. Un igienizator încearcă să facă sigur un conținut periculos; acesta refuză orice nu seamănă cu insigna pe care o cunoaștem deja, iar ruta cade înapoi pe o copie înghețată. Cazul cel mai rău este o insignă de azi-dimineață în loc de o insignă din minutul acesta, ceea ce este un preț care merită plătit ca să nu fie nevoie niciodată să te gândești ce ar putea conține răspunsul altcuiva.
Două dintre refuzuri sunt tocmai despre lucrul pentru care s-a făcut toată această schimbare. Un SVG poate face trimitere la o imagine externă și poate face trimitere la o resursă externă dintr-o declarație de stil. Oricare dintre acestea ar întinde mâna către un terț cu un strat mai adânc decât eticheta pe care tocmai am scos-o, dinăuntrul unui fișier pe care îl servim ca fiind al nostru. O verificare care ar fi căutat doar scripturi le-ar fi lăsat pe amândouă să treacă.
Cădere pe o poză, dinadins
Fiecare drum de eșec întoarce copia înghețată cu starea 200. Eroare de rețea, expirare, o stare care nu este 200, un corp în care verificarea nu are încredere: toate, 200, cu o insignă în el.
Raționamentul este despre cum arată eșecul. Un 404 sau un 502 pe o imagine din subsolul fiecărei pagini înseamnă o pictogramă de imagine stricată pe fiecare pagină, care se citește ca un site stricat, pentru un element decorativ. O insignă puțin veche nu se citește nicicum.
Compensația este că drumul de eșec poartă un antet de cache scurt, în timp ce drumul reușit poartă unul lung. Altfel o pană de cinci minute în amonte ar fixa copia înghețată în fața tuturor pentru toată fereastra de cache.
Există o singură copie înghețată și ea nu trăiește dinadins ca fișier în directorul public. Ca fișier ar avea o a doua adresă publică lângă rută, iar o rundă viitoare ar putea pe bună dreptate să pună o etichetă de imagine care să arate direct spre ea, ceea ce scoate în tăcere comportamentul viu pentru păstrarea căruia există tot acest aranjament. Ținută ca o constantă, singurul fel de a o servi este prin ruta care încearcă mai întâi și rețeaua.
Două cache-uri, cu treburi diferite
Aici sunt două straturi de cache, iar confundarea lor produce un sistem care ori ciocănește sursa din amonte, ori arată octeți învechiți pentru totdeauna.
Cache-ul de date al cadrului de lucru ține răspunsul din amonte: cu o revalidare la șase ore, un vizitator la fiecare șase ore provoacă o singură cerere spre exterior, indiferent de trafic. Antetul de cache HTTP ține răspunsul nostru, la CDN și în browser. Sursa din amonte pune patru ore pe propriul răspuns; șase de partea noastră este cu o jumătate de pas mai larg, pus dinadins, ca o pană de acolo să nu ne lase pe copia înghețată în ritm de patru ore.
O capcană mică, ce a costat o construcție. Next citește configurația de segment de rută static din sursă, deci exportul de revalidare trebuie să fie un număr literal. Scris ca expresie, chiar și ca o constantă declarată cu câteva linii mai jos în același fișier, el întrerupe construcția cu o eroare de configurație de segment nevalidă. Constanta citește acum din export și nu invers, deci există în continuare exact un singur număr.
307-ul care era un semnalizator de pornire
Aceeași rundă a petrecut timp cu ceva ce semăna cu o defecțiune de rutare și nu era, iar asta merită consemnată fiindcă a irosit o rundă întreagă mai devreme.
Rulând construcția de producție local, fiecare cale de marketing simplă răspundea cu 307, redirecționând către sine. Nu căile localizate, nu rutele de API: cele simple. Asta blocase de săptămâni jumătatea engleză a fiecărei baleieri locale de așezare în pagină și fusese consemnată ca defect neexplicat.
Este legarea de gazdă. Pornit cu o adresă de buclă literală ca nume de gazdă, Next lasă valoarea aceea cum este, în timp ce un nume de gazdă gol sau generic este normalizat la localhost. URL-ul inițial și originea pe care o calculează stratul intermediar nu se mai potrivesc atunci, rescrierea rămâne absolută, rutătorul o tratează ca externă și intră din nou. Pornit cu valoarea generică, aceea pe care o folosește producția, sau cu localhost, totul răspunde cu 200.
Nu era nimic de reparat. Ce era de făcut era să scrii linia de pornire corectă în script și să consemnezi de ce, fiindcă un defect care este de fapt un semnalizator va fi altminteri redescoperit de următorul om cu aceeași încredere.
Eșecul pe care am ales să nu îl reparăm
Un al treilea lucru din aceeași rundă este o nereparare intenționată, iar acestea merită consemnate cel puțin la fel de grijuliu ca reparațiile.
Văzuserăm 404-uri de fragmente pe teren: HTML care face trimitere la fișiere JavaScript ce nu mai există. Explicația s-a dovedit a fi un singur antet. Pagina principală poartă o fereastră de stale-while-revalidate măsurată într-un an, deci o margine de CDN are voie să servească HTML dintr-o construcție mai veche pentru foarte multă vreme, iar numele fragmentelor din acel HTML aparțin acelei construcții.
Butonul este chiar acolo și l-am lăsat neatins, fiindcă exact acea copie învechită este ce a ținut site-ul să răspundă în timpul unei bucle de prăbușire a bazei de date cu două săptămâni mai devreme. Scurtarea ferestrei schimbă o încărcare stricată rară pe o pană totală și mai rară. Acesta este un compromis real, el aparține celui care poartă riscul, iar treaba rundei era să explice mecanismul și nu să ia hotărârea.
Ce am consemna
- Un scor uniform pe fiecare pagină arată către ceva ce împart toate paginile. Aceasta este cea mai ieftină pistă pe care o veți primi.
- O etichetă de imagine este o conexiune, nu doar octeți. Tot ce vrea un CDN să facă la o cerere, face și la aceea.
- Găzduirea proprie nu este singura alternativă la încorporare. Aducerea pe server păstrează comportamentul viu și scoate terțul din pagina vizitatorului.
- Odată ce serviți octeții altcuiva, ei sunt ai voștri. Verificați-i și verificați anume trimiterile care ar redeschide gaura pe care tocmai ați închis-o.
- Preferați o poză învechită unei imagini stricate. Pentru decor, un eșec vizibil costă mai mult decât o învechire nevăzută, atâta vreme cât fereastra de învechire este scurtă pe drumul de eșec.
- Nu dați copiei înghețate o adresă publică. Orice se poate atinge va fi până la urmă legat, iar drumul viu va fi ocolit în tăcere.
- Știți care cache ține ce. Unul ține răspunsul din amonte, altul îl ține pe al vostru, iar ferestrele lor răspund la întrebări diferite.
- Unele roșii sunt un semnalizator, nu o defecțiune. Reproduceți mecanismul înainte să reparați simptomul, iar dacă se dovedește a fi propria voastră comandă de pornire, spuneți-o în script.
Ca să fie limpede ce este aceasta: ruta este în producție, iar scorurile vin dintr-o construcție de producție locală pe treizeci și șase de măsurători, nu din date de teren. Explicația celor 404 de fragmente este dedusă din antete și nu a fost reprodusă, iar hotărârea despre acea fereastră de cache aparține omului care poartă riscul de disponibilitate, nu rundei.
Din munca de platformă la Provibr. O altă măsurătoare care era verde din motivul greșit se află în o excepție de accesibilitate care se măsoară, iar un câmp care ținea o intenție acolo unde era locul unui fapt se află în o dată viitoare nu este un calendar.