objekty URL

Vestavěná třída URL poskytuje pohodlné rozhraní pro vytváření a analýzu adres URL.

Neexistují žádné síťové metody, které by přesně vyžadovaly URL objekt, struny jsou dost dobré. Technicky tedy nemusíme používat URL . Ale někdy to může být opravdu užitečné.

Vytvoření adresy URL

Syntaxe pro vytvoření nového URL objekt:

new URL(url, [base])
  • url – úplná adresa URL nebo jediná cesta (pokud je nastavena základna, viz níže),
  • base – volitelná základní adresa URL:pokud je nastavena a url argument má pouze cestu, pak se URL vygeneruje vzhledem k base .

Například:

let url = new URL('https://javascript.info/profile/admin');

Tyto dvě adresy URL jsou stejné:

let url1 = new URL('https://javascript.info/profile/admin');
let url2 = new URL('/profile/admin', 'https://javascript.info');

alert(url1); // https://javascript.info/profile/admin
alert(url2); // https://javascript.info/profile/admin

Můžeme snadno vytvořit novou URL na základě cesty relativní k existující URL:

let url = new URL('https://javascript.info/profile/admin');
let newUrl = new URL('tester', url);

alert(newUrl); // https://javascript.info/profile/tester

URL objekt nám okamžitě umožňuje přístup k jeho komponentám, takže je to pěkný způsob, jak analyzovat adresu URL, např.:

let url = new URL('https://javascript.info/url');

alert(url.protocol); // https:
alert(url.host);     // javascript.info
alert(url.pathname); // /url

Zde je cheatsheet pro komponenty URL:

  • href je úplná adresa URL, stejně jako url.toString()
  • protocol končí dvojtečkou :
  • search – řetězec parametrů, který začíná otazníkem ?
  • hash začíná znakem hash #
  • může tam být také user a password vlastnosti, pokud je přítomna autentizace HTTP:http://login:[email protected] (výše nenabarvené, málo používané).
Můžeme předat URL objektů k síťovým (a většině dalších) metod namísto řetězce

Můžeme použít URL objekt v fetch nebo XMLHttpRequest , téměř všude, kde se očekává řetězec URL.

Obecně URL objekt lze předat libovolné metodě místo řetězce, protože většina metod provede převod řetězce, který změní hodnotu URL objekt do řetězce s úplnou URL.

SearchParams “?…”

Řekněme, že chceme vytvořit adresu URL s danými parametry vyhledávání, například https://google.com/search?query=JavaScript .

Můžeme je poskytnout v řetězci URL:

new URL('https://google.com/search?query=JavaScript')

…Ale parametry je třeba zakódovat, pokud obsahují mezery, jiná písmena než latinka atd. (více o tom níže).

Takže pro to existuje vlastnost adresy URL:url.searchParams , objekt typu URLSearchParams.

Poskytuje pohodlné metody pro parametry vyhledávání:

  • append(name, value) – přidejte parametr o name ,
  • delete(name) – odstraňte parametr o name ,
  • get(name) – získat parametr pomocí name ,
  • getAll(name) – získat všechny parametry se stejným name (to je možné, např. ?user=John&user=Pete ),
  • has(name) – zkontrolujte existenci parametru pomocí name ,
  • set(name, value) – nastavit/nahradit parametr,
  • sort() – řazení parametrů podle názvu, zřídka potřeba,
  • …a je také iterovatelný, podobně jako Map .

Příklad s parametry, které obsahují mezery a interpunkční znaménka:

let url = new URL('https://google.com/search');

url.searchParams.set('q', 'test me!'); // added parameter with a space and !

alert(url); // https://google.com/search?q=test+me%21

url.searchParams.set('tbs', 'qdr:y'); // added parameter with a colon :

// parameters are automatically encoded
alert(url); // https://google.com/search?q=test+me%21&tbs=qdr%3Ay

// iterate over search parameters (decoded)
for(let [name, value] of url.searchParams) {
  alert(`${name}=${value}`); // q=test me!, then tbs=qdr:y
}

Kódování

Existuje standard RFC3986, který definuje, které znaky jsou v adresách URL povoleny a které ne.

Ty, které nejsou povoleny, musí být zakódovány, například písmena a mezery jiné než latinky – nahrazené jejich kódy UTF-8 s předponou % , například %20 (mezera může být kódována + , z historických důvodů, ale to je výjimka).

Dobrou zprávou je, že URL objekty to vše zvládají automaticky. Pouze dodáme všechny parametry nezakódované a poté převedeme URL na řetězec:

// using some cyrillic characters for this example

let url = new URL('https://ru.wikipedia.org/wiki/Тест');

url.searchParams.set('key', 'ъ');
alert(url); //https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D1%81%D1%82?key=%D1%8A

Jak vidíte, obě Тест v cestě url a ъ v parametru jsou zakódovány.

Adresa URL se prodloužila, protože každé písmeno azbuky je v UTF-8 reprezentováno dvěma bajty, takže existují dva %.. entity.

Kódovací řetězce

Za starých časů, před URL se objevily objekty, lidé používali řetězce pro adresy URL.

Od této chvíle URL předměty jsou často pohodlnější, ale stále lze použít i řetězce. V mnoha případech použití řetězce zkracuje kód.

Pokud však použijeme řetězec, musíme speciální znaky zakódovat/dekódovat ručně.

K tomu jsou vestavěné funkce:

  • encodeURI – zakóduje adresu URL jako celek.
  • decodeURI – dekóduje jej zpět.
  • encodeURIComponent – ​​zakóduje komponentu adresy URL, jako je parametr vyhledávání, hash nebo název cesty.
  • decodeURIComponent – ​​dekóduje ji zpět.

Přirozená otázka zní:„Jaký je rozdíl mezi encodeURIComponent a encodeURI ? Kdy bychom měli použít kterýkoli z nich?“

To je snadné pochopit, když se podíváme na adresu URL, která je na obrázku výše rozdělena do částí:

https://site.com:8080/path/page?p1=v1&p2=v2#hash

Jak vidíme, znaky jako : , ? , = , & , # jsou povoleny v URL.

…Na druhou stranu, pokud se podíváme na jednu komponentu URL, jako je parametr vyhledávání, tyto znaky musí být zakódovány, aby nedošlo k porušení formátování.

  • encodeURI kóduje pouze znaky, které jsou v URL zcela zakázány.
  • encodeURIComponent kóduje stejné znaky a kromě nich znaky # , $ , & , + , , , / , : , ; , = , ? a @ .

Takže pro celou URL můžeme použít encodeURI :

// using cyrillic characters in url path
let url = encodeURI('http://site.com/привет');

alert(url); // http://site.com/%D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82

…Zatímco pro parametry URL bychom měli používat encodeURIComponent místo toho:

let music = encodeURIComponent('Rock&Roll');

let url = `https://google.com/search?q=${music}`;
alert(url); // https://google.com/search?q=Rock%26Roll

Porovnejte to s encodeURI :

let music = encodeURI('Rock&Roll');

let url = `https://google.com/search?q=${music}`;
alert(url); // https://google.com/search?q=Rock&Roll

Jak vidíme, encodeURI nekóduje & , protože se jedná o legitimní znak adresy URL jako celku.

Ale měli bychom kódovat & uvnitř vyhledávacího parametru, jinak dostaneme q=Rock&Roll – to je ve skutečnosti q=Rock plus nějaký nejasný parametr Roll . Ne tak, jak bylo zamýšleno.

Měli bychom tedy používat pouze encodeURIComponent pro každý parametr vyhledávání jej správně vložit do řetězce URL. Nejbezpečnější je zakódovat název i hodnotu, pokud si nejsme absolutně jisti, že obsahuje pouze povolené znaky.

Rozdíl v kódování ve srovnání s URL

Třídy URL a URLSearchParams jsou založeny na nejnovější specifikaci URI:RFC3986, zatímco encode* funkce jsou založeny na zastaralé verzi RFC2396.

Je tam pár rozdílů, např. Adresy IPv6 jsou kódovány odlišně:

// valid url with IPv6 address
let url = 'http://[2607:f8b0:4005:802::1007]/';

alert(encodeURI(url)); // http://%5B2607:f8b0:4005:802::1007%5D/
alert(new URL(url)); // http://[2607:f8b0:4005:802::1007]/

Jak vidíme, encodeURI nahradil hranaté závorky [...] , to není správné, důvodem je:adresy URL IPv6 v době RFC2396 (srpen 1998) neexistovaly.

Takové případy jsou vzácné, encode* funkce většinou fungují dobře.