Dlaczego w adresach pojawiają się %20 i %C4%85

Adres URL może zawierać tylko niewielki zestaw znaków: litery, cyfry i kilka symboli. Wszystko inne, spacje, polskie litery, emoji, najpierw zamienia się na bajty UTF-8, a potem każdy bajt zapisuje jako % i dwie cyfry szesnastkowe. Spacja staje się %20, ą staje się %C4%85.

Niektóre znaki nadają strukturę: / oddziela fragmenty ścieżki, ? rozpoczyna query string, & oddziela parametry, = oddziela nazwę od wartości, # wprowadza fragment. Wewnątrz wartości trzeba je zakodować, inaczej psują adres. Na tym polega różnica między encodeURIComponent, które je koduje, a encodeURI, które je zostawia, bo działa na całym adresie.

W formularzach i query stringach spację często zapisuje się też jako +. Dlatego dekodowanie zamienia tu + na spację, tak jak robią to serwery; w ścieżce + pozostaje jednak plusem.

Częste błędy

  • Używanie encodeURI dla wartości parametru: & w wartości dzieli parametr na dwa.
  • Podwójne kodowanie: %20 staje się %2520, a serwer otrzymuje dosłowny tekst %20.
  • Budowanie adresu przez sklejanie niezakodowanych napisów: poza błędami otwiera to drogę do wstrzykiwania parametrów.

Najczęstsze pytania

Czym różni się encodeURI od encodeURIComponent?

encodeURIComponent koduje wszystko poza literami, cyframi i - _ . ! ~ * ' ( ): służy do pojedynczej wartości. encodeURI zostawia też : / ? # [ ] @ & = + $ , ;: służy do gotowego adresu.

Dlaczego spacja to czasem %20, a czasem +?

%20 to ogólne kodowanie spacji w adresie URL. Znak + pochodzi z formularzy HTML (application/x-www-form-urlencoded) i oznacza spację tylko w query stringu.

Czym jest Punycode?

To sposób zapisu w DNS domen ze znakami spoza ASCII, np. żółw.pl jako xn--w-uga1v8h.pl. Przeglądarka pokazuje czytelną postać, ale pod spodem używa zakodowanej.

Jak działa to obliczenie

Kodowanie: tekst zamienia się na bajty UTF-8, a każdy bajt spoza dozwolonego zestawu staje się %HH, gdzie HH to jego wartość szesnastkowa. encodeURIComponent dopuszcza tylko A–Z a–z 0–9 - _ . ! ~ * ' ( ); encodeURI dopuszcza dodatkowo ; , / ? : @ & = + $ #. Dekodowanie: każde %HH wraca do swojego bajtu, bajty są odczytywane jako UTF-8, a + staje się spacją.