Článek
Stačí zkopírovat odkaz s mezerou nebo českým znakem a v některých aplikacích se z něj stane změť procent a hexadecimálních čísel. Místo „č“ se objeví %C4%8D, mezera může být %20 a znak procenta sám skončí jako %25. Na první pohled to vypadá jako šifra. Ve skutečnosti jde o velmi mechanický převod znaků na bajty.
Standard URL od WHATWG definuje percent-encoded byte jako znak % následovaný dvěma hexadecimálními číslicemi. Nejdůležitější je slovo byte. URL neříká „převeď písmeno č na jeden kód“. Nejdřív se text zakóduje do bajtů, typicky v UTF-8, a teprve jednotlivé bajty se zapíší jako %HH.
České „č“ není jeden bajt. Proto z něj vzniknou dva procentní kódy
V Unicode je „č“ jeden znak, ale v UTF-8 se uloží do dvou bajtů: hexadecimálně C4 a 8D. Percent-encoding pak každý bajt zapíše samostatně. Výsledek je %C4%8D.
č -> UTF-8 bajty C4 8D -> %C4%8D
á -> UTF-8 bajty C3 A1 -> %C3%A1
mezera -> bajt 20 -> %20
Proto mají některá česká písmena v zakódované URL šest viditelných znaků: procento, dvě hexadecimální číslice, další procento a další dvě číslice. Není to „dlouhý kód písmena“, ale dva samostatně zapsané bajty.
Vlastní mini-dataset: deset znaků a jejich převod
Pro ověření jsem vzal deset konkrétních znaků a nechal je zakódovat jako samostatnou datovou hodnotu v UTF-8. Ve třetím sloupci je pak serializace ve stylu application/x-www-form-urlencoded, kterou používá URLSearchParams pro query parametry. U strukturálních znaků jako /, ? nebo # záleží na tom, zda jsou součástí syntaxe URL, nebo skutečnými daty uvnitř hodnoty.
Nejvýraznější rozdíl je mezera. Jako percent-encoded bajt je to %20. Při serializaci formulářových query parametrů application/x-www-form-urlencoded se ale mezera zapisuje jako +. Proto můžou dva odkazy vypadat jinak a přitom serveru předat stejnou textovou hodnotu.
%20 a + nejsou univerzálně zaměnitelné
Tady bývá nejčastější zmatek. WHATWG výslovně rozlišuje obecné percent-encoding sady a formulářové kódování. MDN u URLSearchParams připomíná, že při serializaci parametrů se U+0020 SPACE zapisuje jako +. Samotný URL objekt však může v query zachovat mezeru jako %20, takže i v moderním prohlížeči lze při práci s jednou adresou vidět obě podoby.
Znak + má navíc v této formulářové syntaxi zvláštní význam. Pokud potřebujeme skutečné plus jako data, musí se samo zakódovat jako %2B. Jinak může být při parsování vyloženo jako mezera.
Proč se lomítko někdy nechá být a jindy skončí jako %2F
URL není jednolitý text. Má schéma, host, cestu, query a fragment a různé znaky v různých částech plní strukturální funkci. Lomítko v cestě odděluje segmenty, otazník otevírá query a mřížka fragment. Pokud znak funguje jako syntaxe, obvykle zůstává čitelný. Pokud má být součástí datové hodnoty, může být percent-encoded.
Například cesta „/český název“ může být při zápisu UTF-8 reprezentována jako „/%C4%8Desk%C3%BD%20n%C3%A1zev“. Úvodní lomítko zůstává, protože odděluje cestu, zatímco „č“, „ý“ a mezera se zapisují jako bajty.
Proč prohlížeč někdy ukazuje hezké „č“, i když odkaz uvnitř obsahuje procenta
Moderní prohlížeče se snaží adresy zobrazovat čitelně. To znamená, že uživatelské rozhraní může část percent-encoded sekvencí převést zpět na Unicode znaky, i když serializovaná URL pracuje s encoded podobou. Kopírování odkazu mezi aplikacemi proto někdy odhalí víc procentních kódů, než člověk viděl v adresním řádku.
Není to chyba ani změna obsahu. Jde o dvě reprezentace téže informace: čitelnou pro člověka a bezpečně jednoznačnou pro parser URL.
Proč to celé existuje: některé znaky mají v URL práci
Znaky ?, #, &, = nebo / nejsou jen běžná písmena. V určité části URL oddělují komponenty nebo parametry. Percent-encoding umožní říct: „tentokrát tento znak nemá být syntaxe, ale obyčejná data.“
Když má například hodnota vyhledávání obsahovat text „Ben & Jerry“, nesmí neescapované & omylem rozdělit query na další parametr. Proto se v datové hodnotě zapíše jako %26. Stejná logika chrání další vyhrazené znaky.
Verdikt: procenta v URL nejsou šifra. Jsou hexadecimální zápis bajtů
Jakmile člověk ví, že %C4%8D jsou dva UTF-8 bajty a že %20 je hexadecimální hodnota mezery, přestane percent-encoding působit tajemně. Největší zrada zůstává v tom, že pravidla nejsou pro každou část adresy úplně stejná.
Proto dává smysl nepamatovat si desítky kódů nazpaměť. Stačí si odnést tři věci: Unicode text se typicky převede do UTF-8 bajtů, každý zakódovaný bajt dostane podobu %HH a formulářové query má navíc zvláštní tradici, kde se mezera zapisuje jako +.
Zdroje a metodika
WHATWG – URL Standard — Primární standard: definice percent-encoded byte, UTF-8 percent-encoding a rozdílných percent-encode sad.
MDN – URLSearchParams — Praktické vysvětlení serializace application/x-www-form-urlencoded a mezery jako +.
MDN – URL.searchParams — Ukazuje rozdíl mezi URL.search (%20) a serializací URLSearchParams (+).
MDN – encodeURI — Praktický příklad, kde mezera v URL končí jako %20 a vyhrazené znaky mají odlišné chování.





