Cookie di statistica e di pubblicità
Usiamo cookie di statistica e di pubblicità, entrambi inviati a Google. Rifiutare non cambia niente di quello che vedi.Leggi la pagina sulla privacy
Incolla una stringa e ottienila codificata in percentuale per una URL. L’unica decisione che conta viene chiesta invece di essere indovinata: se stai codificando un valore che va dentro una URL, oppure un indirizzo intero le cui barre e i cui punti interrogativi sono struttura e devono sopravvivere. Sbagliare quel verso produce un indirizzo che sembra giusto e porta altrove.
Dove gira
Non viene caricato nulla, perché non c’è nessun file: il calcolo avviene in questa pagina.
Nessuna coda, nessun account
Risponde alla velocità della tua macchina e non chiede mai chi sei.
Tutte le volte che vuoi
Non si conta né si limita nulla: rispondere di nuovo non ci costa niente.
Una URL è fatta di pezzi, e i caratteri che li separano — `/`, `?`, `&`, `=`, `#` — sono struttura quando fanno quel mestiere e dati quando non lo fanno. Codificare un indirizzo intero deve lasciarli stare, altrimenti smette di essere un indirizzo. Codificare un singolo valore deve proteggerli, altrimenti il valore finisce e comincia qualcos’altro.
È esattamente la differenza fra `encodeURI` e `encodeURIComponent`, ed è l’errore che sta dietro alla maggior parte dei parametri di redirect rotti del web: un `?ritorno=https://esempio.it/a?b=c` in cui il secondo punto interrogativo non è mai stato protetto, quindi tutto ciò che segue appartiene alla URL esterna. Il risultato funziona in prova, dove la destinazione non ha parametri, e si rompe in produzione, dove li ha.
Una sequenza percentuale è un `%` seguito da due cifre esadecimali e designa un byte solo. I caratteri fuori dall’ASCII ne richiedono più d’uno: `à` diventa `%C3%A0` e non `%E0`, perché in UTF-8 si scrive con due byte. Un emoji ne richiede quattro.
La vecchia funzione `escape()` produceva invece `%E0` ed è deprecata proprio per questo: è anteriore alla decisione che il web è UTF-8. La sua uscita compare ancora in codice vecchio e in qualche API ereditata, dove decodifica nel carattere sbagliato su qualunque cosa non sia un backend Latin-1. Qui è UTF-8 dappertutto.
`encodeURIComponent` lascia stare cinque caratteri: il punto esclamativo, l'apostrofo dritto, le due parentesi tonde e l'asterisco. La RFC 3986 li elenca fra i caratteri riservati, quindi un codificatore rigorosamente conforme li protegge: le due regole sono in disaccordo su cinque caratteri che nel testo normale compaiono in continuazione.
Nessuno se ne accorge finché non c’è di mezzo una firma. OAuth 1.0 e AWS Signature Version 4 calcolano un hash sulla stringa già codificata, quindi una sola parentesi non protetta cambia l’hash e la richiesta viene respinta — con un errore che parla di credenziali, il che manda a cercare nel posto completamente sbagliato. La modalità stretta qui protegge tutti e cinque.
Compaiono entrambi e non sono la stessa regola. `%20` è codifica percentuale ed è corretto ovunque in una URL. Il segno più viene da `application/x-www-form-urlencoded`, il formato con cui un modulo HTML invia i dati, dove lo spazio si scrive `+`: una convenzione anteriore alla specifica moderna che sopravvive perché sopravvivono i moduli.
In un percorso, `+` è un più letterale. In una query string quasi tutti i server lo leggono come spazio, il che significa che un più vero in un valore va scritto `%2B` o sparisce. Questa pagina produce `%20`, che non è ambiguo in nessuno dei due posti.
Codificare in percentuale una stringa già codificata protegge anche il `%`, quindi `%20` diventa `%2520`. Per nessun componente coinvolto è un errore — è una codifica perfettamente valida del testo letterale «%20» — ed è il motivo per cui la doppia codifica sopravvive fino al punto in cui una persona vede `Ciao%20mondo` in un titolo.
Il segnale è un `%25` dove dovrebbe esserci un `%`. Se lo vedi, qualcosa nella catena sta codificando un valore che era già codificato, di solito perché un framework lo fa per te e un template lo rifà. La correzione è togliere uno dei due passaggi, non decodificare due volte all’arrivo.
Non vanno protetti i separatori quando stanno facendo il loro mestiere: la barra fra due segmenti di percorso, il punto interrogativo che apre la query, la e commerciale fra due parametri, l’uguale fra nome e valore. Proteggerli produce un indirizzo che il server interpreta come un percorso unico e stranissimo, e la risposta è quasi sempre un 404 senza spiegazioni.
Non va protetto nemmeno lo schema: `https%3A%2F%2F` all’inizio di un indirizzo non è una URL, è una stringa. È il tipico effetto di un valore passato per la modalità sbagliata, e si riconosce a occhio proprio dai due caratteri iniziali — se il risultato non comincia con `https://` ma con `https%3A`, hai codificato un indirizzo intero come se fosse un valore.
Tutto quello che segue il `#` resta nel browser: non compare nella richiesta HTTP, non arriva al server e non finisce nei log di accesso. È il motivo per cui i frammenti si usano per lo stato di un’interfaccia, e il motivo per cui un token infilato lì dopo un login OAuth non compare nei log del server.
Non compare non vuol dire che sia protetto. Il frammento è nella barra degli indirizzi, nella cronologia, nei segnalibri e in qualunque estensione che legga l’URL corrente, e viene passato agli script della pagina. Serve a proteggere da una categoria precisa di esposizione, quella dei log lato server, e da nient’altro.
La codifica percentuale vale per il percorso, per la query e per il frammento. Il nome di dominio segue un’altra regola: i caratteri non ASCII si convertono in Punycode, la forma che comincia con `xn--`. Un dominio come `perché.example` viaggia quindi in una scrittura completamente diversa, e non come sequenze di percento.
La conseguenza da conoscere è che due domini diversi possono apparire uguali sullo schermo, perché parecchi alfabeti contengono lettere identiche a quelle latine. È la base degli attacchi di omografia, ed è la ragione per cui la pagina di analisi delle URL su questo sito mostra sempre l’host nella forma Punycode: è l’unica in cui due nomi diversi si vedono diversi.
Quello che si codifica per una URL è quasi sempre un contenuto: un termine di ricerca, il nome di un cliente da mettere in un parametro, una destinazione di redirect che contiene un identificatore di sessione. Sono dati che raccontano qualcosa di preciso su qualcuno.
La codifica è aritmetica su una stringa e non ha nessun bisogno di un server: qui avviene nella pagina, quindi nessuna di quelle stringhe ci arriva. Per il GDPR è la differenza fra un dato che non si è mai mosso e una comunicazione da giustificare, ed è tutta nella scelta di dove far girare qualche riga di codice.
Quasi sempre «un valore dentro una URL»: è il caso di un parametro di query, di un termine di ricerca, di un indirizzo passato come destinazione. «Una URL intera» serve solo quando hai un indirizzo che contiene uno spazio o un carattere accentato e vuoi renderlo legale senza toccarne la struttura. La modalità stretta serve per le firme.
Perché la codifica percentuale nomina byte e non caratteri, e in UTF-8 la à è fatta di due byte: `%C3%A0`. Un emoji ne richiede quattro. La vecchia funzione escape() produceva una sequenza sola, `%E0`, ed è deprecata proprio perché quel risultato è corretto solo su un backend Latin-1.
Che la stringa è stata codificata due volte. `%25` è un segno di percento codificato, quindi `%2520` è la codifica di `%20`, che a sua volta era uno spazio. Vale la pena trovare il punto in cui succede — di solito un framework e un template che proteggono lo stesso valore — invece di decodificare due volte all’arrivo.
`%20` è corretto ovunque in una URL. Il più viene dalla codifica dei moduli HTML e in una query string quasi tutti i server lo leggono come spazio, ma in un percorso è un più letterale. Questa pagina produce sempre %20, che non è ambiguo in nessuno dei due posti; un più vero in un valore va scritto %2B.
No. La codifica avviene nella pagina e non parte nessuna richiesta con quello che hai scritto. Conta perché i valori che si codificano sono spesso termini di ricerca, identificatori e destinazioni di redirect: nessuno di questi ha bisogno di viaggiare per essere protetto.