Preguntas sobre codificación
Signos más, %2520, punycode y por qué el decodificador integrado lanza un error.
¿Qué diferencia hay entre encodeURI y encodeURIComponent?+
encodeURIComponent codifica una parte de una URL y da por hecho que esa parte es un dato, así que escapa los delimitadores que dan forma a una URL: la barra, el signo de interrogación, la almohadilla, el ampersand, el signo igual, los dos puntos, la arroba, el signo más y el signo de dólar. encodeURI codifica una URL que ya está montada y da por hecho que esos delimitadores son estructura, así que los deja como están. La regla práctica es que casi siempre quieres la versión de componente, porque casi siempre estás construyendo una URL a partir de piezas y no arreglando una que ya existe. Recurre a la versión de URL completa solo cuando alguien te pase un enlace completo con un espacio o un carácter acentuado que haya que limpiar.
¿Por qué un espacio es a veces %20 y a veces un signo más?+
Porque se escribieron dos estándares en épocas distintas y los dos han sobrevivido. RFC 3986, que describe las URL en general, codifica un espacio como %20 en todas partes. El formato de envío de formularios HTML, más antiguo, application/x-www-form-urlencoded, codifica un espacio como un signo más, y eso es lo que siguen enviando los navegadores cuando se envía un formulario y lo que produce URLSearchParams. Prácticamente todos los servidores leen bien ambos dentro de una cadena de consulta, porque los analizadores de cadenas de consulta conocen las dos convenciones. El problema empieza cuando un valor codificado de una manera se decodifica de la otra: si decodificas un valor codificado como formulario con un decodificador porcentual simple, un nombre como Anna Marie sale como Anna+Marie. Por eso esta página muestra las dos lecturas de una decodificación en lugar de elegir una por ti.
¿Qué significa %2520?+
Significa un espacio que se codificó dos veces. Un espacio primero se convierte en %20. Si ese %20 vuelve a pasar por un codificador, el propio signo de porcentaje se codifica como %25 y acabas con %2520. Ver %25 seguido de otros dos dígitos hexadecimales en cualquier parte de un enlace es la huella de una doble codificación. Suele ocurrir cuando un parámetro de redirección se construye codificando una URL que ya estaba codificada, o cuando un valor pasa por dos frameworks que lo codifican cada uno con la mejor intención. Pégalo aquí en el modo de decodificación y el recuento de capas te dirá exactamente cuántas pasadas hay que deshacer.
¿Qué caracteres hay que codificar realmente?+
RFC 3986 define un conjunto no reservado que nunca necesita escaparse: de la A a la Z, de la a a la z, del 0 al 9 y los cuatro signos guion, punto, guion bajo y virgulilla. Todo lo demás cae en el conjunto reservado, que se divide en delimitadores generales (dos puntos, barra, signo de interrogación, almohadilla, corchetes, arroba) y subdelimitadores (signo de exclamación, dólar, ampersand, apóstrofo, paréntesis, asterisco, más, coma, punto y coma, igual). Un carácter reservado es válido donde cumple su función estructural y debe escaparse donde es un dato. Además, el espacio y los caracteres comillas dobles, menor que, mayor que, porcentaje, barra invertida, acento circunflejo, acento grave y las llaves no pueden aparecer sin codificar en ningún caso. La tabla de referencia de esta página enumera cada uno con el tratamiento que le dan los cuatro codificadores.
¿Por qué una letra acentuada se convierte en dos códigos de porcentaje?+
Porque la codificación porcentual trabaja con bytes, no con caracteres, y las URL modernas transportan el texto como UTF-8. En UTF-8, la letra e con acento agudo ocupa dos bytes, C3 y A9, así que se codifica como %C3%A9. Un carácter CJK ocupa tres bytes y se convierte en tres tripletes, y un emoji ocupa cuatro bytes y se convierte en cuatro tripletes, es decir, doce caracteres para un solo símbolo visible. Por eso una cadena codificada puede ser varias veces más larga que el texto que escribiste, y por eso un límite de longitud medido en caracteres se comporta de forma distinta antes y después de codificar. La vista de bytes de esta página muestra esa expansión carácter a carácter.
¿Puedo codificar la URL entera para ir sobre seguro?+
No, y es el error que más enlaces rotos produce. Pasar una URL que ya es correcta por un codificador convierte cada carácter estructural en una secuencia de escape: las barras se convierten en %2F, el signo de interrogación en %3F, y el signo de porcentaje de cualquier secuencia de escape existente pasa a ser %25. Lo que sale ya no es una URL, sino una cadena que casualmente se parece a una. Si el enlace ya funciona, déjalo como está. Si un enlace tiene un espacio sin codificar o un carácter acentuado, la codificación de URL completa es la herramienta adecuada, porque los corrige sin tocar los delimitadores. Prueba el ejemplo Ya codificado en el modo de codificación para ver exactamente qué le hace la recodificación a un enlace sano.
¿Qué es punycode y por qué el host se ve distinto de lo que escribí?+
El sistema de nombres de dominio solo transporta un conjunto restringido de caracteres ASCII, así que un dominio escrito en árabe, cirílico, griego, chino o simplemente con una diéresis alemana tiene que traducirse a ASCII antes de poder consultarse. Esa traducción es punycode, y produce etiquetas que empiezan por xn--. El navegador hace esta conversión en silencio, lo que significa que el host que lees y el host que realmente se resuelve son dos cadenas distintas. Mostrar los dos es una comprobación de seguridad, no una curiosidad: un ataque homográfico funciona precisamente porque un nombre formado por caracteres de aspecto parecido se lee como una marca conocida mientras se resuelve en algo completamente distinto. Esta página decodifica el punycode de vuelta a Unicode en el navegador, ya que no hay ninguna forma integrada de invertirlo.
¿Es seguro poner un nombre de usuario y una contraseña en una URL?+
Considera que cualquier credencial que haya aparecido en una URL ya se ha filtrado. La parte de información de usuario de una URL, todo lo que va antes de la arroba, se envía en claro como parte de la línea de petición en protocolos antiguos, se escribe en los registros de acceso del servidor y en los registros de los proxies, se guarda en el historial del navegador y, históricamente, se ha filtrado a través de la cabecera Referer enviada al siguiente sitio que visitas. Algunos navegadores ahora la eliminan o avisan de ella, pero las copias ya escritas en los registros no desaparecen. Si un enlace con credenciales se ha compartido, se ha pegado en un ticket o se ha abierto desde un correo, cambia la contraseña en lugar de confiar en que el enlace siga siendo privado. Esta página marca las credenciales siempre que las encuentra y oculta la contraseña en lugar de mostrarla.
¿Por qué decodeURIComponent lanza un error y qué debo hacer en su lugar?+
Lanza un URIError siempre que la entrada no es una cadena UTF-8 válida con codificación porcentual, lo que incluye un signo de porcentaje sin nada detrás, un par que no es hexadecimal como %ZZ, un carácter multibyte truncado como un %C3 suelto, una codificación sobrelarga y una mitad de par sustituto escapada. El error no indica ni la posición ni la causa, así que en producción suele acabar en una página en blanco o en un error 500. La solución en tu propio código es envolver la llamada y gestionar el fallo de forma explícita en lugar de dejar que se propague. La solución mientras depuras es pegar el valor aquí: el decodificador de esta página recorre la cadena a mano y te dice qué carácter falla y por qué, en lugar de negarse a decirlo.
¿Se envía a un servidor algo de lo que pego?+
No. Todos los codificadores, el decodificador, el analizador de URL, el decodificador de punycode y el editor de consultas se ejecutan en esta pestaña como JavaScript normal, y nunca se accede a ningún enlace. Aquí eso importa más que en la mayoría de las herramientas, porque las URL que la gente lleva a un decodificador son justo las que contienen tokens de sesión, enlaces de descarga firmados, parámetros de restablecimiento de contraseña y nombres de host internos. La entrada está limitada a 100,000 caracteres, mucho más de lo que ocupa cualquier URL utilizable, y no se guarda nada entre visitas.