web-dev-qa-db-fra.com

Quels caractères rendent une URL invalide?

Quels caractères rendent une URL invalide?

Sont ces URL valides?

  • example.com/file[/].html
  • http://example.com/file[/].html
469
good

En général, les URI définis par RFC 3986 (voir Section 2: Caractères ) peuvent contenir l'un des caractères suivants:

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:/?#[]@!$&'()*+,;=

Notez que cette liste n'indique pas où ces caractères peuvent apparaître dans l'URI.

Tout autre caractère doit être codé avec le codage en pourcentage (%hh). Chaque partie de l'URI a des restrictions supplémentaires sur les caractères devant être représentés par un mot codé en pourcentage.

554
Gumbo

Pour ajouter des éclaircissements et répondre directement à la question ci-dessus, plusieurs classes de caractères posent des problèmes pour les URL et les URI.

Certains caractères sont interdits et ne doivent jamais apparaître dans une adresse URL/URI, des caractères réservés (décrits ci-dessous) et d'autres caractères pouvant causer des problèmes dans certains cas, mais portant la mention "imprudent" ou "insalubre". Les explications sur les raisons pour lesquelles les caractères sont limités sont clairement explicitées dans RFC-1738 (URL) et RFC-2396 (URI). Notez que la nouvelle version 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 des caractères non autorisés avec les règles suivantes.

Caractères US-ASCII exclus non autorisés dans la syntaxe d'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 à partir d'un identifiant de fragment. Le pourcentage de caractère "%" 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 non-sages est autorisée mais peut poser problème:

   unwise      = "{" | "}" | "|" | "\" | "^" | "[" | "]" | "`"

Caractères réservés dans un composant de requête et/ou ayant une signification spéciale dans un URI/URL:

  reserved    = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","

La classe de syntaxe "reserved" ci-dessus fait référence aux caractères autorisés dans un URI, mais pouvant ne pas l'être dans un composant particulier de la syntaxe d'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. Il peut donc s'agir de quelque chose comme ftp://user@hostname/ où le caractère '@' a une signification particulière.

Voici un exemple d'URL contenant des caractères non valides et non judicieux (par exemple, '$', '[', ']') et qui devraient être correctement codés:

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 '|' Le caractère (0x7C) bien que seulement marqué comme "imprudent" dans la spécification d'URI lève un URISyntaxException dans le Java Java.net Constructeur .URI , donc une URL telle que http://api.google.com/q?exp=a|b n'est pas autorisée et doit être codée à la place en tant que http://api.google.com/q?exp=a%7Cb si vous utilisez Java avec une instance d'objet URI.

172
JasonM1

La plupart des réponses existantes ne sont pas pratiques car elles ignorent totalement l'utilisation d'adresses réelles telles que:

Tout d'abord, une digression dans la terminologie? Quelles sont ces adresses? Sont-ils des URL valides?

Historiquement, la réponse était "non". Selon 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 de 2005, nous devrions les appeler correctement IRI (Internationalized Resource Identifiers), tels que définis dans RFC 3987 , qui ne sont techniquement pas des URI mais peuvent être convertis en URI simplement en codant tous les pourcentages. 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 s'appellerait auparavant "URI" ou "IRI" en tant que "URL". Cela aligne la terminologie spécifiée avec la manière 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.

Quels personnages sont autorisés en vertu du niveau de vie WHATWG?

Selon ce nouveau sens 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 d'accès, nous sommes autorisés à utiliser des valeurs arbitraires "unités URL" , qui sont:

points de code d'URL et octets codés en pourcentage .

Que sont les "points de code d'URL"?

Les points de code URL sont ASCII alphanumériques, 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 les points de code compris entre U + 00A0 et U + 10FFFD, inclus, à l’exclusion des substituts et des non-caractères.

(Notez que la liste des "points de code d'URL" n'inclut pas _%_, mais que _%_ s sont autorisés dans "Unités de code d'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 d'un caractère quelconque et non dans cet ensemble se trouve dans le hôte , où les adresses IPv6 sont délimitées. _[_ et _]_ caractères. Partout ailleurs dans l'URL, les unités d'URL sont autorisées ou des ensembles de caractères encore plus restrictifs.

Quels personnages étaient autorisés dans les anciennes RFC?

Par souci d’histoire, et comme ce n’est pas exploré ailleurs dans les réponses, examinons ce qui était autorisé dans les anciennes spécifications.

Tout d’abord, nous avons deux types de RFC 3986 caractères réservés :

  • :/?#[]@, 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 du RFC, mais sont réservés à une utilisation en tant que composants syntaxiques de schémas d'URI particuliers. Par exemple, les points-virgules et les virgules sont utilisés dans la syntaxe des RI de données , et _&_ et _=_ sont utilisés dans le format omniprésent _?foo=bar&qux=baz_ dans les chaînes de requête (qui n'est pas spécifié par RFC 3986).

Tous les caractères réservés ci-dessus peuvent être utilisés légalement dans un URI sans codage, que ce soit pour remplir leur fonction syntaxique ou simplement en tant que caractères littéraux dans des données à certains endroits où une telle utilisation ne peut pas être interprétée à tort comme le caractère servant à sa fonction syntaxique. (Par exemple, bien que _/_ ait une signification syntaxique dans une URL, vous pouvez l’utiliser non encodée dans une chaîne de requête, car elle n’a pas de signification dans une chaîne de requête. .)

La RFC 3986 spécifie également des caractères non réservés , qui peuvent toujours être utilisés simplement pour représenter des données sans codage:

  • abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~

Enfin, le caractère _%_ est lui-même autorisé pour les codages en pourcentage.

Cela ne laisse que les ASCII caractères suivants interdits d'apparaître dans une URL:

  • Les caractères de contrôle (caractères 0-1F et 7F), y compris la nouvelle ligne, la tabulation et le retour à la ligne.
  • "<>\^`{|}

Tout autre caractère de ASCII peut figurer légalement dans une URL.

La RFC 3987 étend ensuite ce jeu de caractères non réservés aux 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 compte tenu du dernier Unicode définitions de bloc ; c'est probablement parce que les blocs ont été ajoutés dans la décennie qui a suivi l'écriture de la RFC 3987.


Enfin, il convient peut-être de noter que le fait de savoir quels caractères peuvent apparaître légalement dans une URL ne suffit pas pour déterminer si une chaîne donnée est une URL légale ou non, car certains caractères ne sont légaux que dans certaines parties de l'URL. Par exemple, les caractères réservés _[_ et _]_ sont légaux en tant qu'éléments d'un hôte littéral IPv6 dans une URL de type http: // [1080 :: 8: 800: 200C: 417A]/foo mais ne sont pas légaux dans tout autre contexte, ainsi l'exemple de l'OP de _http://example.com/file[/].html_ est illégal.

73
Mark Amery

Dans votre question complémentaire, vous avez demandé si www.example.com/file[/].html est une URL valide.

Cette URL n'est pas valide car une URL est un type d'URI et un URI valide doit avoir un schéma tel que http: (voir RFC 3986 ).

Si vous vouliez demander si http://www.example.com/file[/].html est une URL valide, la réponse est toujours non, car les caractères entre crochets ne sont pas valides ici.

Les caractères entre crochets sont réservés aux URL de 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 convient de lire attentivement le document RFC 3986 si vous souhaitez comprendre pleinement le problème.

19
Dominic Sayers

Tous les caractères valides pouvant être utilisés dans un URI (a URL est un type de URI ) sont définis dans RFC 3986 .

Tous les autres caractères peuvent être utilisés dans une URL à condition qu'ils soient d'abord "Encodés par URL". Cela implique de changer 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, Référence du codage URL HTML , contient une liste des codages des caractères non valides.

11
CraigTP

Plusieurs plages de caractères Unicode sont valides en HTML5 , bien que leur utilisation puisse ne pas être une bonne idée.

Par exemple, href docs dire http://www.w3.org/TR/html5/links.html#attr-hyperlink-href :

L'attribut href sur un élément 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 indique qu'elle vise à:

Alignez les RFC 3986 et RFC 3987 avec les implémentations contemporaines et les obsolètes.

Ce document définit les points de code d'URL comme:

ASCII alphanumérique, "!", "$", "&", "'", "(", ")", "*", "+", ",", "-", ".", "/" , ":", ";", "=", "?", "@", "_", "~" et des 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 à U + CFFFD, U + D0000 à U + DFFFD, U + E1000 à U + EFFFD, U + F0000 à U + FFFFD, U + 100000 à U + 10FFFD.

Le terme "points de code d'URL" est ensuite utilisé dans la déclaration:

Si c n'est pas un point de code d'URL et pas "%", analyser l'erreur.

dans plusieurs parties de l'algorithme d'analyse, y compris les états de schéma, d'autorité, de chemin relatif, de requête et de fragment: ainsi, en gros, l'URL entière.

De plus, le validateur http://validator.w3.org/ transmet les URL telles que "你好" et ne transmet pas les URL contenant des caractères tels que les espaces "a b"

Bien sûr, comme l'a mentionné Stephen C, il ne s'agit pas uniquement de caractères, mais également de contexte: vous devez comprendre tout l'algorithme. Mais puisque la classe "points de code d'URL" 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 séparer les URL d'une 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{^}|>'

Les choix possibles sont donc la nouvelle ligne, la tabulation, l’espace, la barre oblique inverse et "<>{}^|. Je suppose que je vais aller avec l'espace ou la nouvelle ligne. :)

5
Bunyk

Ce n'est pas vraiment une réponse à votre question, mais valider l'URL est vraiment un problème sérieux. Vous valez probablement mieux de valider le nom de domaine et laisser une partie de la requête dans l'URL. C'est mon expérience. Vous pouvez également recourir à une requête ping sur l'URL et voir si cela donne une réponse valide, mais cela risque d'être trop pour une tâche aussi simple.

Les expressions régulières pour détecter les URL sont abondantes, google it :)

3
ChrisR