¿Qué caracteres hacen que una URL no sea válida?
¿Son estas URL válidas?
example.com/file[/].html
http://example.com/file[/].html
¿Qué caracteres hacen que una URL no sea válida?
¿Son estas URL válidas?
example.com/file[/].html
http://example.com/file[/].html
Respuestas:
En general, los URI definidos por RFC 3986 (consulte la Sección 2: Caracteres ) pueden contener cualquiera de los siguientes 84 caracteres:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:/?#[]@!$&'()*+,;=
Tenga en cuenta que esta lista no indica en qué parte del URI pueden aparecer estos caracteres.
Cualquier otro carácter debe codificarse con el porcentaje de codificación ( %
hh
). Cada parte del URI tiene más restricciones sobre qué caracteres deben ser representados por una palabra codificada en porcentaje.
/^([!#$&-;=?-[]_a-z~]|%[0-9a-fA-F]{2})+$/
¿Hubo algo más que haya encontrado que debería haber aceptado? (Solo para ser claros, esa expresión regular solo verifica si la cadena contiene caracteres de URL válidos, no si la cadena contiene una URL bien formada.)
Para agregar alguna aclaración y abordar directamente la pregunta anterior, hay varias clases de caracteres que causan problemas para las URL y los URI.
Hay algunos caracteres que no están permitidos y que nunca deberían aparecer en una URL / URI, caracteres reservados (descritos a continuación) y otros caracteres que pueden causar problemas en algunos casos, pero están marcados como "imprudentes" o "inseguros". Las explicaciones de por qué los caracteres están restringidos se explican claramente en RFC-1738 (URL) y RFC-2396 (URI). Tenga en cuenta que el RFC-3986 más reciente (actualización de RFC-1738) define la construcción de qué caracteres están permitidos en un contexto dado, pero la especificación anterior ofrece una descripción más simple y más general de los caracteres que no están permitidos con las siguientes reglas.
Caracteres US-ASCII excluidos no permitidos dentro de la sintaxis de URI:
control = <US-ASCII coded characters 00-1F and 7F hexadecimal>
space = <US-ASCII coded character 20 hexadecimal>
delims = "<" | ">" | "#" | "%" | <">
El carácter "#" se excluye porque se usa para delimitar un URI de un identificador de fragmento. El carácter de porcentaje "%" se excluye porque se usa para la codificación de caracteres escapados. En otras palabras, el "#" y el "%" son caracteres reservados que deben usarse en un contexto específico.
La lista de caracteres imprudentes está permitida pero puede causar problemas:
unwise = "{" | "}" | "|" | "\" | "^" | "[" | "]" | "`"
Caracteres que están reservados dentro de un componente de consulta y / o tienen un significado especial dentro de un URI / URL:
reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","
La clase de sintaxis "reservada" anterior se refiere a aquellos caracteres que están permitidos dentro de un URI, pero que pueden no estar permitidos dentro de un componente particular de la sintaxis genérica de URI. Los caracteres en el conjunto "reservado" no están reservados en todos los contextos . El nombre de host, por ejemplo, puede contener un nombre de usuario opcional, por lo que podría ser algo así como ftp://user@hostname/
donde el carácter '@' tiene un significado especial.
Aquí hay un ejemplo de una URL que tiene caracteres no válidos e imprudentes (por ejemplo, '$', '[', ']') y debe codificarse correctamente:
http://mw1.google.com/mw-earth-vectordb/kml-samples/gp/seattle/gigapxl/$[level]/r$[y]_c$[x].jpg
Algunas de las restricciones de caracteres para URI / URL dependen del lenguaje de programación. Por ejemplo, el '|' (0x7C), aunque solo está marcado como "imprudente" en la especificación de URI, arrojará una URISyntaxException en el constructor Java java.net.URI, por lo que una URL como http://api.google.com/q?exp=a|b
no está permitida y debe codificarse como http://api.google.com/q?exp=a%7Cb
si estuviera utilizando Java con una instancia de objeto URI.
?
está bien en la sección de consulta, pero es imposible antes, y no creo que @
pertenezca a ninguna de estas listas. Ah, y en lugar de %25
en la última cadena, ¿no quieres decir %7C
?
La mayoría de las respuestas existentes aquí no son prácticas porque ignoran totalmente el uso de direcciones en el mundo real como:
Primero, una digresión en la terminología. ¿Cuáles son estas direcciones? ¿Son URL válidas?
Históricamente, la respuesta fue "no". Según RFC 3986 , desde 2005, tales direcciones no son URI (y, por lo tanto, no son URL, ya que las URL son un tipo de URI ). Según la terminología de los estándares IETF de 2005, deberíamos llamarlos adecuadamente IRI (Identificadores de recursos internacionalizados), tal como se define en RFC 3987 , que técnicamente no son URI pero pueden convertirse a URI simplemente codificando todos los caracteres no ASCII en el IRI. .
Según las especificaciones modernas, la respuesta es "sí". El WHATWG Living Standard simplemente clasifica todo lo que anteriormente se llamaría "URI" o "IRI" como "URL". Esto alinea la terminología especificada con la forma en que las personas normales que no han leído la especificación usan la palabra "URL", que era uno de los objetivos de la especificación .
Según este nuevo significado de "URL", ¿qué caracteres están permitidos? En muchas partes de la URL, como la cadena de consulta y la ruta, podemos usar "unidades URL" arbitrarias , que son
¿Qué son los "puntos de código URL"?
Los puntos del código URL son alfanuméricos ASCII, U + 0021 (!), U + 0024 ($), U + 0026 (&), U + 0027 ('), U + 0028 PARENTESIS IZQUIERDA, U + 0029 PARENTESIS DERECHA, U + 002A (*), U + 002B (+), U + 002C (,), U + 002D (-), U + 002E (.), U + 002F (/), U + 003A (:), U + 003B (;), U + 003D (=), U + 003F (?), U + 0040 (@), U + 005F (_), U + 007E (~) y puntos de código en el rango U + 00A0 a U + 10FFFD, inclusive, excluyendo sustitutos y no personajes.
(Tenga en cuenta que la lista de "puntos de código URL" no incluye %
, pero que %
se permiten en "unidades de código URL" si son parte de una secuencia de codificación porcentual).
El único lugar que puedo detectar donde la especificación permite el uso de cualquier carácter que no esté en este conjunto es en el host , donde se incluyen las direcciones IPv6 [
y los ]
caracteres. En cualquier otro lugar de la URL, se permiten unidades de URL o algún conjunto de caracteres aún más restrictivo.
Por el bien de la historia, y dado que no se explora por completo en ninguna otra parte de las respuestas aquí, examinemos que estaba permitido bajo el par de especificaciones más antiguas.
En primer lugar, tenemos dos tipos de caracteres reservados RFC 3986 :
:/?#[]@
, que forman parte de la sintaxis genérica para un URI definido en RFC 3986!$&'()*+,;=
, que no forman parte de la sintaxis genérica de RFC, pero están reservadas para su uso como componentes sintácticos de esquemas de URI particulares. Por ejemplo, puntos y comas y comas se utilizan como parte de la sintaxis de URIs de datos , y &
y =
se utilizan como parte de la omnipresente ?foo=bar&qux=baz
formato en cadenas de consulta (que no está especificado por el RFC 3986).Cualquiera de los caracteres reservados arriba se puede usar legalmente en un URI sin codificación, ya sea para cumplir su propósito sintáctico o simplemente como caracteres literales en los datos en algunos lugares donde dicho uso no puede ser malinterpretado como el carácter que cumple su propósito sintáctico. (Por ejemplo, aunque /
tiene un significado sintáctico en una URL, puede usarlo sin codificar en una cadena de consulta, porque no tiene significado en una cadena de consulta).
RFC 3986 también especifica algunos caracteres no reservados , que siempre se pueden usar simplemente para representar datos sin ninguna codificación:
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~
Finalmente, el %
carácter en sí está permitido para codificaciones porcentuales.
Eso deja solo los siguientes caracteres ASCII que tienen prohibido aparecer en una URL:
"<>\^`{|}
Todos los demás caracteres de ASCII pueden aparecer legalmente en una URL.
Luego, RFC 3987 extiende ese conjunto de caracteres no reservados con los siguientes rangos de caracteres unicode:
%xA0-D7FF / %xF900-FDCF / %xFDF0-FFEF
/ %x10000-1FFFD / %x20000-2FFFD / %x30000-3FFFD
/ %x40000-4FFFD / %x50000-5FFFD / %x60000-6FFFD
/ %x70000-7FFFD / %x80000-8FFFD / %x90000-9FFFD
/ %xA0000-AFFFD / %xB0000-BFFFD / %xC0000-CFFFD
/ %xD0000-DFFFD / %xE1000-EFFFD
Estas opciones de bloque de la especificación anterior parecen extrañas y arbitrarias dadas las últimas definiciones de bloque Unicode ; Esto probablemente se deba a que los bloques se han agregado en la década desde que se escribió RFC 3987.
Finalmente, quizás valga la pena señalar que el simple hecho de saber qué caracteres pueden aparecer legalmente en una URL no es suficiente para reconocer si una cadena dada es una URL legal o no, ya que algunos caracteres solo son legales en determinadas partes de la URL. Por ejemplo, los caracteres reservados [
y ]
son legales como parte de un host literal IPv6 en una URL como http: // [1080 :: 8: 800: 200C: 417A] / foo pero no son legales en ningún otro contexto, por lo que El ejemplo de OP http://example.com/file[/].html
es ilegal.
En su pregunta complementaria, preguntó si www.example.com/file[/].html
es una URL válida.
Esa URL no es válida porque una URL es un tipo de URI y una URI válida debe tener un esquema como http:
(ver RFC 3986 ).
Si pretendía preguntar si http://www.example.com/file[/].html
es una URL válida, entonces la respuesta sigue siendo no porque los caracteres de corchetes no son válidos allí.
Los caracteres de corchete están reservados para las URL en este formato: http://[2001:db8:85a3::8a2e:370:7334]/foo/bar
(es decir, un literal IPv6 en lugar de un nombre de host)
Vale la pena leer el RFC 3986 detenidamente si desea comprender el problema por completo.
[
y ]
no son URI válidos para casi analizadores que he visto. Esto realmente me ha jodido en el mundo real: stackoverflow.com/questions/11038967/…
Unwise
muy en serio para los URI y, sin embargo, estarán bien con las bibliotecas de URL. Es decir, no hay bandera para ignorar Unwise
. Tendré que verificar qué Rust lang (ya que se está construyendo para un navegador, tengo curiosidad por saber qué hace) para las URL. Sin embargo, la mayoría de los navegadores también pasarán "[", "]". Entonces, en teoría, como dije con C / C ++, son sub / super, pero la realidad no es tan cierta. Depende en gran medida de la interpretación de las especificaciones y la semántica de super / subconjunto.
Todos los caracteres válidos que se pueden usar en un URI (una URL es un tipo de URI ) se definen en RFC 3986 .
Todos los demás caracteres se pueden usar en una URL siempre que primero estén "codificados con URL". Esto implica cambiar el carácter no válido para "códigos" específicos (generalmente en forma de símbolo de porcentaje (%) seguido de un número hexadecimal).
Este enlace, Referencia de codificación de URL HTML , contiene una lista de las codificaciones de caracteres no válidos.
Varios de los rangos de caracteres Unicode son HTML5 válidos , aunque aún podría no ser una buena idea usarlos.
Por ejemplo, los href
documentos dicen http://www.w3.org/TR/html5/links.html#attr-hyperlink-href :
El atributo href en un elemento de área debe tener un valor que sea una URL válida potencialmente rodeada de espacios.
Luego, la definición de "URL válida" apunta a http://url.spec.whatwg.org/ , que dice que apunta a:
Alinee RFC 3986 y RFC 3987 con implementaciones contemporáneas y desactívelas en el proceso.
Ese documento define los puntos de código URL como:
ASCII alfanumérico, "!", "$", "&", "'", "(", ")", "*", "+", ",", "-", ".", "/" , ":", ";", "=", "?", "@", "_", "~" y puntos de código en los rangos U + 00A0 a U + D7FF, U + E000 a U + FDCF , U + FDF0 a U + FFFD, U + 10000 a U + 1FFFD, U + 20000 a U + 2FFFD, U + 30000 a U + 3FFFD, U + 40000 a U + 4FFFD, U + 50000 a U + 5FFFD, U +60000 a U + 6FFFD, U + 70000 a U + 7FFFD, U + 80000 a U + 8FFFD, U + 90000 a U + 9FFFD, U + A0000 a U + AFFFD, U + B0000 a U + BFFFD, U + C0000 a U + CFFFD, U + D0000 a U + DFFFD, U + E1000 a U + EFFFD, U + F0000 a U + FFFFD, U + 100000 a U + 10FFFD.
El término "puntos de código URL" se usa en la declaración:
Si c no es un punto de código URL y no es "%", analice el error.
en varias partes del algoritmo de análisis, incluidos el esquema, la autoridad, la ruta relativa, la consulta y los estados de fragmentos: básicamente, la URL completa.
Además, el validador http://validator.w3.org/ pasa por URL como "你好"
, y no pasa por URL con caracteres como espacios"a b"
Por supuesto, como mencionó Stephen C, no se trata solo de personajes sino también de contexto: hay que entender todo el algoritmo. Pero dado que la clase "puntos de código URL" se usa en puntos clave del algoritmo, eso da una buena idea de lo que puede usar o no.
Ver también: caracteres Unicode en URL
Necesito seleccionar un carácter para dividir las URL en una cadena, así que decidí crear una lista de caracteres que yo no podría encontrar en la URL:
>>> allowed = "-_.~!*'();:@&=+$,/?%#[]?@ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
>>> from string import printable
>>> ''.join(set(printable).difference(set(allowed)))
'`" <\x0b\n\r\x0c\\\t{^}|>'
Por lo tanto, las opciones posibles son la nueva línea, la pestaña, el espacio, la barra diagonal inversa y "<>{}^|
. Supongo que iré con el espacio o la nueva línea. :)
Realmente no es una respuesta a su pregunta, pero validar la URL es realmente una pregunta seria. Probablemente sea mejor validar el nombre de dominio y dejar la consulta como parte de la url. Esa es mi experiencia. También podría recurrir a hacer ping a la URL y ver si da como resultado una respuesta válida, pero eso podría ser demasiado para una tarea tan simple.
Las expresiones regulares para detectar las URL son abundantes, google :)
Estoy implementando el antiguo lector / escritor de solicitudes y respuestas http (0.9, 1.0, 1.1). Solicitar URI es el lugar más problemático.
No puede usar RFC 1738, 2396 o 3986 tal como está. Hay muchos clientes y servidores HTTP antiguos que permiten más caracteres. Así que he hecho la investigación basada en los registros de acceso del servidor web publicadas por accidente: "GET URI HTTP/1.0" 200
.
Descubrí que los siguientes caracteres no estándar a menudo se usan en URI:
\ { } < > | ` ^ "
Estos caracteres fueron descritos en RFC 1738 como inseguros .
Si desea ser compatible con todos los clientes y servidores HTTP antiguos, debe permitir estos caracteres en el URI de solicitud.
Lea más información sobre esta investigación en http-og .
Se me ocurrió un par de expresiones regulares para PHP que convertirán las URL en texto en etiquetas de anclaje. (Primero convierte todas las URL de www. A http: // luego convierte todas las URL con https?: // a enlaces href = ... html
$string = preg_replace('/(https?:\/\/)([!#$&-;=?\-\[\]_a-z~%]+)/sim', '<a href="$1$2">$2</a>',
preg_replace('/(\s)((www\.)([!#$&-;=?\-\[\]_a-z~%]+))/sim', '$1http://$2', $string)
);