Codifica URL
Trasforma il testo in qualcosa che si può mettere dentro un URL, nella modalità giusta per dove deve finire.
Che cos'è la codifica URL?
La codifica URL, o percent-encoding, sostituisce i caratteri che in un URL hanno un significato, o che non ci possono stare, con un segno di percentuale e il loro valore esadecimale. Lo spazio diventa %20, il punto interrogativo %3F. È ciò che permette a un testo qualsiasi di viaggiare dentro un indirizzo.
Come funziona
Il percent-encoding sostituisce un byte con un % e le sue due cifre esadecimali. Lo spazio diventa %20, la e commerciale %26, e tutto ciò che sta fuori dall’ASCII viene codificato come byte UTF-8: la è sono due byte, quindi diventa %C3%A8.
È la modalità a decidere cosa resta intatto, ed è tutto lì. Codificare un singolo valore protegge i delimitatori & = ? / #, perché dentro una query string sono punteggiatura. Codificare un indirizzo intero li lascia stare, perché lì sono la struttura.
La terza modalità serve ai corpi dei form, dove lo spazio si scrive + invece di %20. È lo stesso standard con un’eccezione storica, e usarla nel posto sbagliato è il modo in cui un segno più dentro un valore sparisce.
Che cos’è il percent-encoding e perché a un URL serve
Un URL ha un alfabeto ristretto: lettere, cifre, qualche segno e un insieme di caratteri riservati che significano qualcosa di strutturale. Il ? apre la query, l’& separa i parametri, l’= divide il nome dal valore, il # comincia il frammento, la / separa i segmenti del percorso. Mettine uno dentro un valore e il parser lo legge come punteggiatura, perché non ha modo di sapere che lo intendevi alla lettera.
Il percent-encoding è la via d’uscita. Ogni byte che non può comparire tale e quale si scrive come % seguito dal suo valore in esadecimale, così l’& diventa %26 e il parser vede un carattere qualunque dove ci sarebbe stato un separatore. Tutto ciò che è fuori dall’ASCII passa prima per UTF-8, ed è il motivo per cui una lettera accentata occupa due sequenze e un’emoji quattro.
Le tre modalità e quando serve ciascuna
- Un valore per qualcosa che va dentro una query string o un segmento di percorso: un termine di ricerca, il nome di una campagna, un indirizzo di destinazione. Codifica & = ? / # e gli spazi. È quello che fa encodeURIComponent, ed è la modalità che serve nove volte su dieci.
- URL intero per un indirizzo già montato a cui vanno solo ripuliti i caratteri illegali. Lascia : / ? # & = al loro posto così l’URL continua a funzionare. È encodeURI, e usarlo su un singolo valore è l’errore classico: l’& dentro il tuo valore sopravvive e spacca il parametro in due.
- Campo form per un corpo application/x-www-form-urlencoded, dove lo spazio si scrive + per una convenzione più vecchia della specifica degli URL. Per il resto identica alla prima.
- Leggere la tabella dei parametri quando l’input contiene una query string, i parametri compaiono sotto, già decodificati. Di solito si legge più in fretta della riga codificata.
I casi che rompono un link
Un indirizzo di destinazione dentro un parametro è dove la cosa morde di più. Per mandare qualcuno a ?next=https://example.com/a?b=1 la destinazione va codificata per intero come valore, altrimenti il suo ? e il suo & vengono letti come parte dell’URL esterno e l’indirizzo arriva troncato. Codificata bene diventa https%3A%2F%2Fexample.com%2Fa%3Fb%3D1: illeggibile, ed esattamente giusta.
La doppia codifica è lo stesso errore nell’altro verso. Codifica una stringa già codificata e %20 diventa %2520, perché viene codificato anche il % stesso. Il sintomo visibile è un valore che arriva con dentro delle sequenze percentuali letterali, e la causa è quasi sempre un valore codificato una volta dal tuo codice e una volta dal framework.
E il segno più è una trappola a due facce. Nel corpo di un form il + vale spazio, quindi la stringa «C++» inviata grezza arriva come «C ». Fuori da un form il + è un più letterale, e decodificarlo come spazio corrompe qualsiasi valore base64 che ne contenga uno. Per questo qui la modalità è una scelta e mai un indovinello.
Quando qualcosa non torna
- Un parametro arriva tagliato a metà il valore conteneva un & non codificato e il server l’ha letto come inizio del parametro successivo. Codifica il valore, non l’URL.
- Gli spazi compaiono come %20 nel testo della pagina qualcosa ha codificato un valore già codificato, oppure ha codificato un valore che poi è stato mostrato invece che usato.
- %2520 da qualsiasi parte doppia codifica, sempre. Decodifica una volta e verifica se la codifica spetta al tuo codice o al framework, poi togline una.
- Gli accenti escono come è da qualche parte nella catena i byte sono stati codificati in Latin-1 invece che in UTF-8. Il percent-encoding moderno è UTF-8; qualunque altra cosa va dichiarata esplicitamente.
- Il frammento non arriva mai al server è voluto. Tutto quello che segue il # resta nel browser e non viene mai inviato, quindi codificarlo non cambia nulla di ciò che il server riceve.
Il vocabolario intorno
- Caratteri riservati : / ? # [ ] @ ! $ & ’ ( ) * +, ; =: quelli con un compito strutturale, che vanno codificati per usarli alla lettera.
- Caratteri non riservati A–Z a–z 0–9 - . _ ~: non hanno mai bisogno di codifica, e codificarli comunque è lecito ma inutile.
- encodeURI contro encodeURIComponent le modalità «URL intero» e «un valore» qui sopra. I nomi sono di JavaScript, la distinzione è della RFC 3986.
- Punycode un meccanismo diverso per una parte diversa: i nomi di dominio non ASCII diventano ASCII con prefisso xn--, perché la parte host non può contenere sequenze percentuali.
- Base64 e base64url codifica per byte, non per URL. Il Base64 standard contiene + e /, ed è il motivo per cui la variante per URL li sostituisce con - e _.
Domande frequenti
Che cosa significa %20 in un URL?
È uno spazio. Il percent-encoding scrive ogni byte non ammesso come % più due cifre esadecimali, e 0x20 è lo spazio ASCII.
Che differenza c’è tra encodeURI e encodeURIComponent?
encodeURI lascia intatti i caratteri che danno struttura all’URL (: / ? # & =), quindi serve per un indirizzo intero. encodeURIComponent codifica anche quelli, quindi serve per un singolo valore da mettere dentro un URL.
Perché una lettera accentata diventa due codici?
Perché il percent-encoding lavora sui byte e il testo passa prima per UTF-8. La è sono i due byte C3 A8, quindi diventa %C3%A8. Un’emoji ne occupa quattro.
Quando lo spazio è + invece di %20?
Nel corpo application/x-www-form-urlencoded, dove il + significa spazio da prima della specifica degli URL. In ogni altro posto il + è un più letterale.
Da cosa viene %2520?
Da una doppia codifica: una stringa già codificata è stata codificata di nuovo, quindi il % di %20 è diventato %25. Di solito il valore viene codificato una volta dal codice e una dal framework.