Codificarea URL înlocuiește un caracter cu semnul procent și două cifre hexadecimale: un spațiu devine %20, un ampersand devine %26, un semn de întrebare devine %3F. Scopul este să oprești citirea unui caracter ca sintaxă URL atunci când tu l-ai vrut ca date. Nimic mai mult.
Motivul pentru care pare mai complicat decât atât este că aproape fiecare întrebare despre asta este de fapt o întrebare despre scop. Care caractere, în care parte a URL-ului, codificate de care strat? Greșești scopul și obții una din două defecțiuni clasice: un parametru de tracking care se trunchiază pe tăcute, sau o destinație care ajunge ca https%3A%2F%2Fexample.com și dă 404. Acest articol acoperă cele două seturi de caractere care decid răspunsul, locurile unde regulile se schimbă, și cum verifici ce transportă de fapt un link. Pentru imaginea mai largă a ceea ce face o redirecționare cu toate astea, vezi tipurile de redirecționări.
Cele două seturi care decid totul
Secțiunea 2.3 din RFC 3986 definește un set nerezervat care nu are niciodată nevoie de codificare: litere, cifre și exact patru semne de punctuație - liniuță, punct, underscore, tildă. Dacă valoarea ta conține doar acestea, nu ai nimic de făcut.
Tot restul se împarte în două categorii. Caracterele rezervate au un rol structural: : / ? # [ ] @ separă părțile unui URL, iar ! $ & ' ( ) * + , ; = separă lucruri în interiorul acelor părți. Secțiunea 2.2 le listează. Sunt legale ca sintaxă și trebuie codificate atunci când apar ca date. Restul este tot ce se află în afara ASCII, care este codificat octet cu octet după conversia la UTF-8 - motiv pentru care o literă cu diacritice costă de obicei șase caractere, nu trei.
Asta ne dă singura regulă care merită memorată: codifică un caracter atunci când este date și altfel ar fi citit ca sintaxă. Un ampersand între doi parametri este sintaxă. Un ampersand în interiorul unui nume de campanie este date, și dacă îl lași necodificat, lista de parametri se termină acolo.
Codifică valoarea, nu URL-ul
Asta este greșeala pe care o văd cel mai des, și are mereu aceeași formă. Cineva are un URL, știe că are nevoie de codificare, așa că lipește tot în interiorul unui encoder și obține:
https%3A%2F%2Fexample.com%2Fspring%3Futm_campaign%3Dspring%20sale
Acel șir nu este un URL. Este o bucată de text cu formă de URL care poate fi doar o valoare în interiorul altui URL - exact locul unde își are rostul atunci când treci o destinație printr-un redirector, și exact locul unde nu își are rostul atunci când încerci să îl deschizi.
Tratamentul corect codifică fiecare valoare separat:
https://example.com/spring?utm_campaign=spring%20sale&utm_source=flyer
Schema, host-ul, separatorii de cale și ? și & sunt lăsați ca sintaxă. Doar valoarea s-a schimbat. Fiecare limbaj vine cu două funcții pentru această distincție, iar alegerea celei greșite este cealaltă jumătate a problemei: pagina MDN despre encodeURIComponent spune fără menajamente că encodeURI lasă intenționat caracterele rezervate neschimbate pentru că se așteaptă la un URI complet, în timp ce encodeURIComponent le codifică pentru că se așteaptă la un fragment dintr-unul. Valorile au nevoie de encodeURIComponent. În Python este urllib.parse.quote, în Go url.QueryEscape, în PHP rawurlencode.
Spațiul este %20, cu excepția cazului în care este un plus
Amândouă sunt corecte, în locuri diferite, și acesta este cel mai derutant lucru din tot subiectul.
Într-o cale sau într-un URI generic, un spațiu este %20. Într-un query string construit așa cum îl construiește un formular HTML, un spațiu este +, pentru că asta specifică serializarea application/x-www-form-urlencoded din standardul URL WHATWG. Ambele forme sunt citite ca spațiu de orice parser de query de pe server pe care ai putea să-l întâlnești.
Capcana este direcția inversă. Dacă semnul plus este date - un număr de telefon, un termen de căutare, o campanie numită spring+summer - trebuie scris %2B. Lăsat necodificat într-un query string, devine spațiu, și vei petrece o după-amiază întrebându-te de ce numărul din CRM-ul tău și-a pierdut codul de țară.
| Caracter | Codificat | De ce contează |
|---|---|---|
| space | %20 or + | + doar în interiorul unui query string, %20 oriunde altundeva |
& | %26 | Necodificat, lista de parametri se termină acolo |
? | %3F | Necodificat, tot ce urmează devine query-ul |
# | %23 | Necodificat, restul nu ajunge niciodată la server |
+ | %2B | Necodificat într-un query, ajunge ca spațiu |
% | %25 | Necodificat, următoarele două caractere sunt înghițite |
Rândul cu # merită o mențiune, pentru că el este cel care produce cel mai derutant raport de bug. Un fragment nu este niciodată trimis către server. Pune un # necodificat într-o țintă de redirecționare, și serverul vede un URL trunchiat, în timp ce bara de adrese a browserului arată în continuare corect, așa că persoana care raportează asta jură că linkul e în regulă.
Dacă îți construiești URL-urile de campanie de mână mai mult decât ocazional, oprește-te: generatorul nostru de UTM codifică fiecare valoare pe măsură ce scrii, iar convențiile de denumire UTM acoperă alegerea unor valori care nu au nevoie de codificare de la bun început. Scurtează rezultatul pe propriul tău domeniu și mizeria codificată nu mai este ceva la care trebuie să se uite cineva.
Dubla codificare, și cum o recunoști
Dubla codificare este ce se întâmplă atunci când o valoare trece prin două straturi care își fac fiecare treaba. Semnul procent este el însuși un caracter care trebuie codificat, așa că %20 devine %2520, iar %2520 devine %252520.
Simptomele sunt de recunoscut, o dată ce le-ai văzut. Un titlu de pagină care afișează spring%20sale unui vizitator real. Un parametru care ajunge în analytics cu secvențe de codificare vizibile. O redirecționare care funcționează la primul hop și dă greș la al doilea. Cauza este aproape întotdeauna un apel de codificare aplicat peste o valoare care a ajuns deja codificată, de multe ori pentru că a venit dintr-o bază de date care stoca forma codificată.
Soluția este să decizi care strat deține codificarea și să faci ca celelalte să nu se mai implice. Decodifică o singură dată când citești o valoare, codifică o singură dată când o scrii într-un URL, și nu face niciodată amândouă în aceeași funcție.
Unde mușcă asta în practică
Trei locuri, în ordinea în care probabil le vei întâlni.
Parametri de tracking. O valoare de campanie cu un ampersand necodificat trunchiază lista de parametri, așa că sesiunea ajunge în analytics ca trafic direct, iar campania nu primește niciun credit. Nimic nu dă eroare. Parametrii UTM care nu apar în GA4 acoperă diagnoza din perspectiva raportării, iar browserele elimină parametrii UTM acoperă cealaltă cauză pentru care un parametru poate dispărea între click și pagină.
Redirecționări. Regulile serverului recodifică inconsecvent, iar dacă un query string supraviețuiește deloc depinde de directiva folosită. O redirecționare 301 în .htaccess are tabelul complet pentru Apache; varianta scurtă este că o regulă care înlocuiește query string-ul îl va elimina pe al tău pe tăcute.
Coduri QR. Codificarea infla lungimea payload-ului, iar lungimea payload-ului decide cât de dens este codul tipărit. Fiecare spațiu costă trei caractere în loc de unul, fiecare literă cu diacritice șase. Un URL de tracking cu câteva nume de campanie codificate poate ridica un cod cu o versiune sau două, ceea ce este o diferență reală la dimensiunea unei cărți de vizită - codul QR care nu se scanează pune lungimea payload-ului printre cele patru cauze exact din acest motiv. Codificarea unui link scurt în loc de URL-ul complet este cea mai ieftină soluție disponibilă.
Verifică ce transportă de fapt un link
Două comenzi rezolvă aproape orice dispută. Prima arată ce primește serverul după o redirecționare:
curl -sI 'https://example.com/spring?utm_campaign=spring%20sale' | grep -i '^location'
A doua construiește codificarea pentru tine, în loc să se bazeze pe degetele tale, ceea ce este util atunci când o valoare conține mai mulți vinovați deodată:
curl -G --data-urlencode 'utm_campaign=spring & summer sale' \
--data-urlencode 'utm_source=flyer' \
-o /dev/null -w '%{url_effective}\n' https://example.com/spring
Citește rezultatul ca date, nu ca decorație. Dacă vezi %2520 ai o problemă de dublă codificare, dacă vezi o valoare care se termină prea devreme ai un separator necodificat, iar dacă vezi %3A%2F%2F la început ai codificat tot URL-ul. Verificatorul nostru de linkuri face partea de redirecționare într-un browser, dacă preferi să nu deschizi un terminal.
Obiceiul care merită format este să te uiți o dată la URL-ul final, cu ochiul liber, înainte ca o campanie să fie lansată. Bug-urile de codificare sunt invizibile într-un browser și evidente într-un terminal, și te costă atribuire, nu uptime, motiv pentru care supraviețuiesc atât de mult.
Citește seria fundamentală
Acest articol face parte din clusterul engineering. Pentru partea de redirecționare, tipurile de redirecționări acoperă fiecare cod de stare și metodă client-side, iar cum funcționează serviciile de scurtare URL acoperă ce se întâmplă între click și pagină.
Alte articole de pe blog
Întrebări frecvente
Ce este codificarea URL?
Înlocuirea unui caracter cu semnul procent urmat de valoarea sa în octeți, scrisă hexadecimal, astfel încât caracterul să nu poată fi confundat cu sintaxă URL. Un spațiu devine %20, un ampersand devine %26, un semn de întrebare devine %3F. Mecanismul este definit în RFC 3986 și se mai numește și percent-encoding.
Ce caractere trebuie codificate pentru URL?
Orice se află în afara setului nerezervat, pe care RFC 3986 îl definește ca litere, cifre și cele patru caractere: liniuță, punct, underscore și tildă. Tot restul este fie punctuație rezervată care are un rol structural, fie un octet aflat în afara ASCII, și ambele trebuie codificate procentual atunci când apar în interiorul unei valori, nu ca sintaxă.
Ar trebui să codific întregul URL sau doar părți din el?
Doar părțile. Trecerea unui URL complet printr-un encoder transformă https://example.com în https%3A%2F%2Fexample.com, care nu mai este deloc un URL. Codifică separat fiecare valoare de parametru din query și fiecare segment de cale, și lasă neschimbate schema, host-ul și separatorii.
Este un spațiu %20 sau semnul plus?
Amândouă, în locuri diferite. Într-o cale și într-un URI generic, un spațiu este %20. Într-un query string construit așa cum îl construiesc formularele HTML, un spațiu este semnul plus, pentru că așa specifică serializarea application/x-www-form-urlencoded. Un plus literal în interiorul unei valori din query trebuie deci scris %2B, altfel va fi citit ca spațiu.
Ce este dubla codificare?
Codificarea a ceva ce era deja codificat, astfel încât %20 devine %2520, pentru că semnul procent este el însuși codificat, devenind %25. Simptomul este o pagină care afișează literal %20 în text, sau un parametru care ajunge cu secvențe de codificare vizibile. Este aproape întotdeauna o valoare trecută prin două straturi care, fiecare, au codificat-o cu bune intenții.
De ce fac caracterele codificate un cod QR mai greu de scanat?
Pentru că fiecare costă trei caractere în loc de unul. Un spațiu este un caracter de intenție și trei de payload, așa că o mână de asemenea caractere poate ridica codul cu o versiune sau două, ceea ce înseamnă mai multe module pe aceeași suprafață tipărită. Codificarea unui URL lung de tracking într-un cod QR este unul dintre cele mai rapide moduri de a obține un cod care se scanează doar de la mică distanță.
Încearcă Elido
Lipește un URL, obții un link scurt funcțional
Fără înregistrare. Linkul este activ timp de 30 de zile. Înregistrează-te ca să-l păstrezi pentru totdeauna.
Gratuit, fără înregistrare · 2 pe zi