La clase URL incorporada brinda una interfaz conveniente para crear y analizar URLs.
No hay mtodos de networking que requieran exactamente un objeto URL, los strings son suficientemente buenos para eso. As que tcnicamente no tenemos que usar URL. Pero a veces puede ser realmente til.
Creando una URL
La sintaxis para crear un nuevo objeto URL es:
new URL(url, [base])
urlLa URL completa o ruta nica (si se establece base, mira a continuacin),baseuna URL base opcional: si se establece y el argumentourlsolo tiene una ruta, entonces la URL se genera relativa abase.
Por ejemplo:
let url = new URL('https://javascript.info/profile/admin');
Estas dos URLs son las mismas:
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
Fcilmente podemos crear una nueva URL basada en la ruta relativa a una URL existente:
let url = new URL('https://javascript.info/profile/admin');
let newUrl = new URL('tester', url);
alert(newUrl); // https://javascript.info/profile/tester
El objeto URL inmediatamente nos permite acceder a sus componentes, por lo que es una buena manera de analizar la url, por ej.:
let url = new URL('https://javascript.info/url');
alert(url.protocol); // https:
alert(url.host); // javascript.info
alert(url.pathname); // /url
Aqu est la hoja de trucos para los componentes URL:
hrefes la url completa, igual queurl.toString()protocolacaba con el carcter dos puntos:searchun string de parmetros, comienza con el signo de interrogacin?hashcomienza con el carcter de hash#- Tambin puede haber propiedades
userypasswordsi la autenticacin HTTP esta presente:http://login:password@site.com(no mostrados arriba, raramente usados)
URL a mtodos de red (y la mayora de los dems) en lugar de un stringPodemos usar un objeto URL en fetch o XMLHttpRequest, casi en todas partes donde se espera un URL-string.
Generalmente, un objeto URL puede pasarse a cualquier mtodo en lugar de un string, ya que la mayora de mtodos llevarn a cabo la conversin del string, eso convierte un objeto URL en un string con URL completa.
Parmetros de bsqueda ?
Digamos que queremos crear una url con determinados parmetros de bsqueda, por ejemplo, https://google.com/search?query=JavaScript.
Podemos proporcionarlos en el string URL:
new URL('https://google.com/search?query=JavaScript')
Pero los parmetros necesitan estar codificados si contienen espacios, letras no latinas, entre otros (Ms sobre eso debajo).
Por lo que existe una propiedad URL para eso: url.searchParams, un objeto de tipo URLSearchParams.
Esta proporciona mtodos convenientes para los parmetros de bsqueda:
append(name, value)aade el parmetro porname,delete(name)elimina el parmetro porname,get(name)obtiene el parmetro porname,getAll(name)obtiene todos los parmetros con el mismoname(Eso es posible, por ej.?user=John&user=Pete),has(name)comprueba la existencia del parmetro porname,set(name, value)establece/reemplaza el parmetro,sort()ordena parmetros porname, raramente necesitado,- y adems es iterable, similar a
Map.
Un ejemplo con parmetros que contienen espacios y signos de puntuacin:
let url = new URL('https://google.com/search');
url.searchParams.set('q', 'test me!'); // Parmetro aadido con un espacio y !
alert(url); // https://google.com/search?q=test+me%21
url.searchParams.set('tbs', 'qdr:y'); // Parmetro aadido con dos puntos :
// Los parmetros son automticamente codificados
alert(url); // https://google.com/search?q=test+me%21&tbs=qdr%3Ay
// Iterar sobre los parametros de bsqueda (Decodificados)
for(let [name, value] of url.searchParams) {
alert(`${name}=${value}`); // q=test me!, then tbs=qdr:y
}
Codificacin
Existe un estndar RFC3986 que define cuales caracteres son permitidos en URLs y cuales no.
Esos que no son permitidos, deben ser codificados, por ejemplo letras no latinas y espacios reemplazados con sus cdigos UTF-8, con el prefijo %, tal como %20 (un espacio puede ser codificado con +, por razones histricas, pero esa es una excepcin).
La buena noticia es que los objetos URL manejan todo eso automticamente. Nosotros slo proporcionamos todos los parmetros sin codificar, y luego convertimos la URL a string:
// Usando algunos caracteres cirlicos para este ejemplo
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
Como puedes ver, ambos en la ruta url y en el parmetro estn codificados.
La URL se alarga, ya que cada letra cirlica es representada con dos bytes en UTF-8, por lo que hay dos entidades %...
Codificando strings
En los viejos tiempos, antes de que los objetos URL aparecieran, la gente usaba strings para las URL.
A partir de ahora, los objetos URL son frecuentemente ms convenientes, pero tambin an pueden usarse los strings. En muchos casos usando un string se acorta el cdigo.
Aunque si usamos un string, necesitamos codificar/decodificar caracteres especiales manualmente.
Existen funciones incorporadas para eso:
- encodeURI Codifica la URL como un todo.
- decodeURI La decodifica de vuelta.
- encodeURIComponent Codifica un componente URL, como un parametro de busqueda, un hash, o un pathname.
- decodeURIComponent La decodifica de vuelta.
Una pregunta natural es: "Cul es la diferencia entre encodeURIComponent y encodeURI?Cundo deberamos usar una u otra?
Eso es fcil de entender si miramos a la URL, que est separada en componentes en la imagen de arriba:
https://site.com:8080/path/page?p1=v1&p2=v2#hash
Como podemos ver, caracteres tales como :, ?, =, &, # son admitidos en URL.
Por otra parte, si miramos a un nico componente URL, como un parmetro de bsqueda, estos caracteres deben estar codificados, para no romper el formateo.
encodeURICodifica solo caracteres que estn totalmente prohibidos en URLencodeURIComponentCodifica los mismos caracteres, y, en adicin a ellos, los caracteres#,$,&,+,,,/,:,;,=,?y@.
Entonces, para una URL completa podemos usar encodeURI:
// Usando caracteres cirlicos en el path URL
let url = encodeURI('http://site.com/');
alert(url); // http://site.com/%D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82
Mientras que para parmetros URL deberamos usar encodeURIComponent en su lugar:
let music = encodeURIComponent('Rock&Roll');
let url = `https://google.com/search?q=${music}`;
alert(url); // https://google.com/search?q=Rock%26Roll
Compralo con encodeURI:
let music = encodeURI('Rock&Roll');
let url = `https://google.com/search?q=${music}`;
alert(url); // https://google.com/search?q=Rock&Roll
Como podemos ver, encodeURI no codifica &, ya que este es un carcter legtimo en la URL como un todo.
Pero debemos codificar & dentro de un parmetro de bsqueda, de otra manera, obtendremos q=Rock&Roll- que es realmente q=Rock ms algn parmetro Roll oscuro. No segn lo previsto.
As que debemos usar solo encodeURIComponentpara cada parmetro de bsqueda, para insertarlo correctamente en el string URL. Lo ms seguro es codificar tanto nombre como valor, a menos que estemos absolutamente seguros de que solo haya admitido caracteres
URLLas clases URL y URLSearchParams estn basadas en la especificacin URI mas reciente: RFC3986, mientras que las funciones encode* estn basadas en la versin obsoleta RFC2396.
Existen algunas diferencias, por ej. las direcciones IPv6 se codifican de otra forma:
// Url vlida con direccin IPv6
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]/
Como podemos ver, encodeURI reemplaz los corchetes [...], eso es incorrecto, la razn es: las urls IPv6 no existan en el tiempo de RFC2396 (August 1998).
Tales casos son raros, las funciones encode* mayormente funcionan bien.
Comentarios
<code>, para varias lneas envolverlas en la etiqueta<pre>, para ms de 10 lneas utilice una entorno controlado (sandbox) (plnkr, jsbin, codepen)