Quels caractères rendent une URL invalide?
Ces URL sont-elles valides?
example.com/file[/].html
http://example.com/file[/].html
Quels caractères rendent une URL invalide?
Ces URL sont-elles valides?
example.com/file[/].html
http://example.com/file[/].html
Réponses:
En général, les URI tels que définis par la RFC 3986 (voir Section 2: Caractères ) peuvent contenir l'un des 84 caractères suivants:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:/?#[]@!$&'()*+,;=
Notez que cette liste n'indique pas où dans l'URI ces caractères peuvent apparaître.
Tout autre caractère doit être codé avec le pourcentage de codage ( %
hh
). Chaque partie de l'URI a des restrictions supplémentaires sur les caractères qui doivent être représentés par un mot codé en pourcentage.
/^([!#$&-;=?-[]_a-z~]|%[0-9a-fA-F]{2})+$/
Y avait-il autre chose que vous aviez trouvé qu'il aurait dû accepter? (Juste pour être clair, cette expression régulière vérifie uniquement si la chaîne contient des caractères d'URL valides, pas si la chaîne contient une URL bien formée.)
Pour ajouter des éclaircissements et répondre directement à la question ci-dessus, il existe plusieurs classes de caractères qui causent des problèmes pour les URL et les URI.
Certains caractères sont interdits et ne doivent jamais apparaître dans une URL / URI, des caractères réservés (décrits ci-dessous) et d'autres caractères qui peuvent provoquer des problèmes dans certains cas, mais sont marqués comme «imprudents» ou «dangereux». Les explications pour lesquelles les caractères sont restreints sont clairement énoncées dans la RFC-1738 (URL) et la RFC-2396 (URI). Notez que la nouvelle RFC-3986 (mise à jour de la RFC-1738) définit la construction des caractères autorisés dans un contexte donné, mais l'ancienne spécification offre une description plus simple et plus générale de quels caractères ne sont pas autorisés avec les règles suivantes.
Caractères US-ASCII exclus non autorisés dans la syntaxe URI:
control = <US-ASCII coded characters 00-1F and 7F hexadecimal>
space = <US-ASCII coded character 20 hexadecimal>
delims = "<" | ">" | "#" | "%" | <">
Le caractère "#" est exclu car il est utilisé pour délimiter un URI d'un identifiant de fragment. Le caractère de pourcentage "%" est exclu car il est utilisé pour le codage des caractères d'échappement. En d'autres termes, les "#" et "%" sont des caractères réservés qui doivent être utilisés dans un contexte spécifique.
La liste des caractères imprudents est autorisée mais peut provoquer des problèmes:
unwise = "{" | "}" | "|" | "\" | "^" | "[" | "]" | "`"
Caractères réservés dans un composant de requête et / ou ayant une signification particulière dans un URI / URL:
reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","
La classe de syntaxe "réservée" ci-dessus fait référence aux caractères autorisés dans un URI, mais qui peuvent ne pas l'être dans un composant particulier de la syntaxe URI générique. Les caractères de l'ensemble "réservé" ne sont pas réservés dans tous les contextes . Le nom d'hôte, par exemple, peut contenir un nom d'utilisateur facultatif, ce qui pourrait être quelque chose comme ftp://user@hostname/
où le caractère «@» a une signification spéciale.
Voici un exemple d'URL qui a des caractères invalides et imprudents (par exemple '$', '[', ']') et doit être correctement encodé:
http://mw1.google.com/mw-earth-vectordb/kml-samples/gp/seattle/gigapxl/$[level]/r$[y]_c$[x].jpg
Certaines restrictions de caractères pour les URI / URL dépendent du langage de programmation. Par exemple, le '|' (0x7C) caractère bien que marqué comme « imprudents » dans la spécification URI jetteront un URISyntaxException dans Java java.net.URI constructeur si une URL comme http://api.google.com/q?exp=a|b
n'est pas autorisée et doit être codé au lieu que http://api.google.com/q?exp=a%7Cb
si vous utilisez Java avec une instance d'objet URI.
?
est très bien dans la section de requête, mais impossible avant, et je ne pense pas qu'il @
appartient à aucune de ces listes. Oh, et au lieu de %25
dans la dernière chaîne, tu ne veux pas dire %7C
?
La plupart des réponses existantes ici ne sont pas pratiques car elles ignorent totalement l'utilisation dans le monde réel d'adresses comme:
Tout d'abord, une digression dans la terminologie. Quelles sont ces adresses? S'agit-il d'URL valides?
Historiquement, la réponse était "non". Selon la RFC 3986 , à partir de 2005, ces adresses ne sont pas des URI (et donc pas des URL, car les URL sont un type d'URI ). Selon la terminologie des normes IETF 2005, nous devrions les appeler correctement IRI (Internationalized Resource Identifiers), tels que définis dans la RFC 3987 , qui ne sont techniquement pas des URI mais qui peuvent être convertis en URI simplement en encodant en pourcentage tous les caractères non ASCII dans l'IRI .
Selon les spécifications modernes, la réponse est "oui". Le WHATWG Living Standard classe simplement tout ce qui serait auparavant appelé "URI" ou "IRI" comme "URL". Cela aligne la terminologie spécifiée sur la façon dont les personnes normales qui n'ont pas lu la spécification utilisent le mot "URL", qui était l'un des objectifs de la spécification .
Selon cette nouvelle signification de "URL", quels caractères sont autorisés? Dans de nombreuses parties de l'URL, telles que la chaîne de requête et le chemin, nous sommes autorisés à utiliser des "unités d'URL" arbitraires , qui sont
Que sont les «points de code URL»?
Les points de code URL sont alphanumériques ASCII, U + 0021 (!), U + 0024 ($), U + 0026 (&), U + 0027 ('), U + 0028 PARENTHÈSE GAUCHE, U + 0029 PARENTHÈSE DROITE, 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 (~) et points de code dans la plage U + 00A0 à U + 10FFFD, inclus, à l'exclusion des substituts et des non-caractères.
(Notez que la liste des "points de code URL" ne comprend pas %
, mais que les %
s sont autorisés dans les "unités de code URL" s'ils font partie d'une séquence de codage en pourcentage.)
Le seul endroit où je peux repérer où la spécification autorise l'utilisation de tout caractère qui n'est pas dans cet ensemble est dans l' hôte , où les adresses IPv6 sont incluses entre les caractères [
et ]
. Partout ailleurs dans l'URL, les unités d'URL sont autorisées ou un ensemble de caractères encore plus restrictif.
Par souci d'histoire, et comme cela n'est pas exploré complètement ailleurs dans les réponses ici, examinons ce qui était autorisé sous l'ancienne paire de spécifications.
Tout d'abord, nous avons deux types de caractères réservés RFC 3986 :
:/?#[]@
, qui font partie de la syntaxe générique d'un URI défini dans la RFC 3986!$&'()*+,;=
, qui ne font pas partie de la syntaxe générique de la RFC, mais sont réservés à une utilisation en tant que composants syntaxiques de schémas URI particuliers. Par exemple, des points - virgules et les virgules sont utilisés dans le cadre de la syntaxe des URIs de données , et &
et =
sont utilisés dans le cadre de l'omniprésent ?foo=bar&qux=baz
format dans les chaînes de requête (qui ne sont pas spécifié par la RFC 3986).N'importe lequel des caractères réservés ci-dessus peut être légalement utilisé dans un URI sans codage, soit pour servir leur objectif syntaxique, soit comme caractères littéraux dans les données à certains endroits où une telle utilisation ne peut pas être mal interprétée comme le caractère servant son objectif syntaxique. (Par exemple, bien qu'il /
ait une signification syntaxique dans une URL, vous pouvez l'utiliser non codé dans une chaîne de requête, car il n'a pas de signification dans une chaîne de requête.)
La RFC 3986 spécifie également certains caractères non réservés , qui peuvent toujours être utilisés simplement pour représenter des données sans aucun encodage:
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~
Enfin, le %
caractère lui-même est autorisé pour les encodages en pourcentage.
Cela ne laisse que les caractères ASCII suivants qui sont interdits d'apparaître dans une URL:
"<>\^`{|}
Tout autre caractère ASCII peut légalement figurer dans une URL.
La RFC 3987 étend ensuite cet ensemble de caractères non réservés avec les plages de caractères unicode suivantes:
%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
Ces choix de bloc de l'ancienne spécification semblent bizarres et arbitraires étant donné les dernières définitions de bloc Unicode ; cela est probablement dû au fait que les blocs ont été ajoutés au cours de la décennie écoulée depuis la rédaction de la RFC 3987.
Enfin, il convient peut-être de noter que le simple fait de savoir quels caractères peuvent légalement apparaître dans une URL n'est pas suffisant pour reconnaître si une chaîne donnée est une URL légale ou non, car certains caractères ne sont légaux que dans des parties particulières de l'URL. Par exemple, les caractères réservés [
et ]
sont autorisés dans le cadre d'un hôte littéral IPv6 dans une URL telle que http: // [1080 :: 8: 800: 200C: 417A] / foo mais ne sont pas autorisés dans un autre contexte, de sorte que le L'exemple d'OP http://example.com/file[/].html
est illégal.
Dans votre question supplémentaire, vous avez demandé si l' www.example.com/file[/].html
URL était valide.
Cette URL n'est pas valide car une URL est un type d'URI et un URI valide doit avoir un schéma comme http:
(voir RFC 3986 ).
Si vous vouliez demander si http://www.example.com/file[/].html
une URL est valide, la réponse est toujours non, car les caractères entre crochets ne sont pas valides à cet endroit.
Les caractères entre crochets sont réservés aux URL dans ce format: http://[2001:db8:85a3::8a2e:370:7334]/foo/bar
(c'est-à-dire un littéral IPv6 au lieu d'un nom d'hôte)
Il vaut la peine de lire attentivement la RFC 3986 si vous voulez bien comprendre le problème.
[
et ]
ne sont pas valides pour presque les analyseurs que j'ai vus. Cela m'a en fait vissé dans le monde réel: stackoverflow.com/questions/11038967/…
Unwise
très au sérieux pour les URI et pourtant seront très bien avec les bibliothèques d'URL. C'est qu'il n'y a pas de drapeau à ignorer Unwise
. Je vais devoir vérifier ce que Rust lang (car il est construit pour un navigateur, je suis curieux de savoir ce qu'il fait) pour les URL. Cependant, la plupart des navigateurs passeront volontiers "[", "]". Donc, en théorie, comme je l'ai dit avec C / C ++, ils sont sub / super mais la réalité n'est pas si vraie. Il dépend fortement de l'interprétation de la spécification et de la sémantique du super / sous-ensemble.
Tous les caractères valides qui peuvent être utilisés dans un URI (une URL est un type d' URI ) sont définis dans la RFC 3986 .
Tous les autres caractères peuvent être utilisés dans une URL à condition qu'ils soient d'abord "URL encodés". Cela implique de modifier le caractère non valide pour des "codes" spécifiques (généralement sous la forme du symbole de pourcentage (%) suivi d'un nombre hexadécimal).
Ce lien, HTML URL Encoding Reference , contient une liste des encodages pour les caractères non valides.
Plusieurs des plages de caractères Unicode sont HTML5 valides , bien que ce ne soit toujours pas une bonne idée de les utiliser.
Par exemple, les href
documents indiquent http://www.w3.org/TR/html5/links.html#attr-hyperlink-href :
L'attribut href sur les éléments a et area doit avoir une valeur qui est une URL valide potentiellement entourée d'espaces.
Ensuite, la définition de "URL valide" pointe vers http://url.spec.whatwg.org/ , qui dit qu'elle vise à:
Alignez la RFC 3986 et la RFC 3987 avec les implémentations contemporaines et obsolètes dans le processus.
Ce document définit les points de code URL comme:
ASCII alphanumérique, "!", "$", "&", "'", "(", ")", "*", "+", ",", "-", ".", "/" , ":", ";", "=", "?", "@", "_", "~" et les points de code dans les plages U + 00A0 à U + D7FF, U + E000 à U + FDCF , U + FDF0 à U + FFFD, U + 10000 à U + 1FFFD, U + 20000 à U + 2FFFD, U + 30000 à U + 3FFFD, U + 40000 à U + 4FFFD, U + 50000 à U + 5FFFD, U +60000 à U + 6FFFD, U + 70000 à U + 7FFFD, U + 80000 à U + 8FFFD, U + 90000 à U + 9FFFD, U + A0000 à U + AFFFD, U + B0000 à U + BFFFD, U + C0000 vers U + CFFFD, U + D0000 vers U + DFFFD, U + E1000 vers U + EFFFD, U + F0000 vers U + FFFFD, U + 100000 vers U + 10FFFD.
Le terme "points de code URL" est ensuite utilisé dans la déclaration:
Si c n'est pas un point de code URL et non "%", erreur d'analyse.
dans plusieurs parties de l'algorithme d'analyse, y compris le schéma, l'autorité, le chemin relatif, les états de requête et de fragment: donc fondamentalement l'URL entière.
De plus, le validateur http://validator.w3.org/ passe pour les URL comme "你好"
, et ne passe pas pour les URL avec des caractères comme des espaces"a b"
Bien sûr, comme l'a mentionné Stephen C, il ne s'agit pas seulement de personnages mais aussi de contexte: il faut comprendre tout l'algorithme. Mais puisque la classe "URL code points" est utilisée sur les points clés de l'algorithme, elle donne une bonne idée de ce que vous pouvez utiliser ou non.
Voir aussi: Caractères Unicode dans les URL
Je dois sélectionner un caractère pour fractionner les URL en chaîne, j'ai donc décidé de créer une liste de caractères qui ne pouvaient pas être trouvés dans l'URL par moi-même:
>>> allowed = "-_.~!*'();:@&=+$,/?%#[]?@ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
>>> from string import printable
>>> ''.join(set(printable).difference(set(allowed)))
'`" <\x0b\n\r\x0c\\\t{^}|>'
Ainsi, les choix possibles sont la nouvelle ligne, tabulation, espace, barre oblique inverse et "<>{}^|
. Je suppose que j'irai avec l'espace ou la nouvelle ligne. :)
Pas vraiment une réponse à votre question, mais la validation des URL est vraiment un problème sérieux Vous êtes probablement mieux de valider le nom de domaine et de laisser une partie de la requête de l'URL. Telle est mon expérience. Vous pouvez également recourir à la commande ping de l'URL et voir si elle aboutit à une réponse valide, mais cela peut être trop pour une tâche aussi simple.
Les expressions régulières pour détecter les URL sont abondantes, google it :)
J'implémente un ancien lecteur / rédacteur de requêtes et de réponses http (0.9, 1.0, 1.1). L'URI de demande est l'endroit le plus problématique.
Vous ne pouvez pas simplement utiliser RFC 1738, 2396 ou 3986 tel quel. Il existe de nombreux anciens clients et serveurs HTTP qui autorisent plus de caractères. J'ai donc fait la recherche basée sur les journaux d'accès du serveur Web accidentellement publié: "GET URI HTTP/1.0" 200
.
J'ai trouvé que les caractères non standard suivants sont souvent utilisés dans l'URI:
\ { } < > | ` ^ "
Ces caractères ont été décrits dans la RFC 1738 comme dangereux .
Si vous souhaitez être compatible avec tous les anciens clients et serveurs HTTP - vous devez autoriser ces caractères dans l'URI de demande.
Veuillez lire plus d'informations sur cette recherche dans http-og .
J'ai trouvé quelques expressions régulières pour PHP qui convertiront les URL du texte en balises d'ancrage. (D'abord, il convertit toutes les URL www. En http: // puis convertit toutes les URL avec https?: // en liens 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)
);