Caractères autorisés dans une URL

191

Quelqu'un connaît-il la liste complète des caractères qui peuvent être utilisés dans un GET sans être encodés? Pour le moment, j'utilise AZ az et 0-9 ... mais je cherche à découvrir la liste complète.

Je suis également intéressé de savoir s'il existe une spécification publiée pour l'ajout à venir d'URL chinoises et arabes (car cela aura évidemment un impact important sur ma question)

marque
la source
5
Les caractères autorisés dans un URI sont réservés !*'();:@&=+$,/?#[]ou non réservés A-Za-z0-9_.~-(ou un caractère de pourcentage %dans le cadre d'un encodage en pourcentage)
Mikl
1
Dans MySQL, j'utilise ceci REGEXP '[^]A-Za-z0-9_.~!*''();:@&=+$,/?#[%-]+'pour trouver une chaîne d'URL avec des caractères incorrects. Peut-être que c'est aussi utile pour quelqu'un d'autre.
Mikl
@Mikl: Cette chose ne ressemble guère à une expression régulière.
Jens Mander

Réponses:

182

À partir de la spécification RFC 1738 :

Ainsi, seuls les caractères alphanumériques, les caractères spéciaux " $-_.+!*'()," et les caractères réservés utilisés à leurs fins réservées peuvent être utilisés non codés dans une URL.

EDIT: Comme @Jukka K. Korpela le souligne correctement, cette RFC a été mise à jour par RFC 3986 . Cela a élargi et clarifié les caractères valides pour l'hôte, malheureusement ce n'est pas facile à copier et à coller, mais je ferai de mon mieux.

Dans le premier ordre correspondant:

host        = IP-literal / IPv4address / reg-name

IP-literal  = "[" ( IPv6address / IPvFuture  ) "]"

IPvFuture   = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )

IPv6address =         6( h16 ":" ) ls32
                  /                       "::" 5( h16 ":" ) ls32
                  / [               h16 ] "::" 4( h16 ":" ) ls32
                  / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
                  / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
                  / [ *3( h16 ":" ) h16 ] "::"    h16 ":"   ls32
                  / [ *4( h16 ":" ) h16 ] "::"              ls32
                  / [ *5( h16 ":" ) h16 ] "::"              h16
                  / [ *6( h16 ":" ) h16 ] "::"

ls32        = ( h16 ":" h16 ) / IPv4address
                  ; least-significant 32 bits of address

h16         = 1*4HEXDIG 
               ; 16 bits of address represented in hexadecimal

IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet

dec-octet   = DIGIT                 ; 0-9
              / %x31-39 DIGIT         ; 10-99
              / "1" 2DIGIT            ; 100-199
              / "2" %x30-34 DIGIT     ; 200-249
              / "25" %x30-35          ; 250-255

reg-name    = *( unreserved / pct-encoded / sub-delims )

unreserved  = ALPHA / DIGIT / "-" / "." / "_" / "~"     <---This seems like a practical shortcut, most closely resembling original answer

reserved    = gen-delims / sub-delims

gen-delims  = ":" / "/" / "?" / "#" / "[" / "]" / "@"

sub-delims  = "!" / "$" / "&" / "'" / "(" / ")"
              / "*" / "+" / "," / ";" / "="

pct-encoded = "%" HEXDIG HEXDIG
Myles
la source
5
@Tim slash est un caractère réservé, donc, s'il est utilisé pour son usage réservé (délimitation des chemins, délimitation de protocole ...), il n'a pas besoin d'être échappé. Sinon, c'est le cas.
Myles
4
Les règles de syntaxe générique de la RFC 1738 sont devenues obsolètes en 1998.
Jukka K. Korpela
3
@Myles, STD 66 (= RFC 3986) est mentionné dans d'autres réponses. La question de savoir si le contenu des réponses est correct est une autre question; Je ne pense pas qu'aucune des réponses décrit correctement la liste complète.
Jukka K. Korpela
4
Et vous pouvez ajouter une liste de A-Za-z0-9_.-~caractères non réservés et réservés au début de cette réponse. !*'();:@&=+$,/?#[]Cela peut faire gagner du temps aux gens
Mikl
2
@basZero Je suis désolé que vous ayez trouvé cela déroutant, mais la réponse complète n'est pas simple. La réponse à votre question est non, car il s'agit d'un caractère réservé comme indiqué par:reserved = gen-delims / sub-delims gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
Myles
42

Les caractères autorisés dans un URI sont réservés ou non réservés (ou un caractère de pourcentage dans le cadre d'un encodage en pourcentage)

http://en.wikipedia.org/wiki/Percent-encoding#Types_of_URI_characters

dit que ce sont des caractères RFC 3986 non réservés (sec. 2.3) ainsi que des caractères réservés (sec 2.2) s'ils doivent conserver leur signification spéciale. Et aussi un caractère de pourcentage dans le cadre d'un encodage en pourcentage.

ambre
la source
7
Bien que ce lien puisse répondre à la question, il est préférable d'inclure les parties essentielles de la réponse ici et de fournir le lien pour référence. Les réponses aux liens uniquement peuvent devenir invalides si la page liée change.
jaestevan
@jaestevan Citation du document lié:The characters allowed in a URI are either reserved or unreserved (or a percent character as part of a percent-encoding)
Mikl
26

La liste complète des 66 caractères non réservés se trouve dans la RFC3986, ici: http://tools.ietf.org/html/rfc3986#section-2.3

Il s'agit de n'importe quel caractère de l'ensemble de regex suivant:

[A-Za-z0-9_.\-~]
slacy
la source
2
Vous pouvez également utiliser ceux réservés.
Qwerty
La RFC1738 obsolète est répertoriée {}^\~et n'est backtickpas sûre. Et RFC3986 répertorie \ comme dangereux à cause du système de fichiers. Ce moyen {}^pourrait également être utilisé.
mgutt
Donc, si vous essayez, par exemple, de trouver la fin d'une URL dans une chaîne (ce que je suis), il serait préférable de suivre les normes obsolètes dans la réponse acceptée ... Si vous validez les URL, vous devriez utilisez le jeu de caractères sur cette réponse.
ashleedawg
Attention, vous avez écrit ceci comme une classe de caractères d'expression régulière. Assurez-vous d'échapper -ou de le mettre au début ou à la fin de la classe de caractères, car il [.-~]contient en fait tous les caractères ASCII de 46 à 126.
kwl
19

Je l'ai testé en demandant mon site Web (apache) avec tous les caractères disponibles sur mon clavier allemand comme paramètre d'URL:

http://example.com/?^1234567890ß´qwertzuiopü+asdfghjklöä#<yxcvbnm,.-°!"§$%&/()=? `QWERTZUIOPÜ*ASDFGHJKLÖÄ\'>YXCVBNM;:_²³{[]}\|µ@€~

Celles-ci n'ont pas été encodées:

^0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,.-!/()=?`*;:_{}[]\|~

Non encodé après urlencode():

0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_

Non encodé après rawurlencode():

0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_~

Remarque: avant PHP 5.3.0 rawurlencode()encodé à ~cause de la RFC 1738 . Mais cela a été remplacé par RFC 3986, donc son utilisation est sûre maintenant. Mais je ne comprends pas pourquoi par exemple {}sont encodés rawurlencode()car ils ne sont pas mentionnés dans la RFC 3986.

Un test supplémentaire que j'ai fait concernait la liaison automatique dans les textes de courrier. J'ai testé Mozilla Thunderbird, aol.com, outlook.com, gmail.com, gmx.de et yahoo.de et ils ont entièrement lié des URL contenant ces caractères:

0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_~+#,%&=*;:@

Bien sûr, le ?était également lié, mais seulement s'il était utilisé une fois.

Certaines personnes suggèrent maintenant de n'utiliser que le rawurlencode() caractères, mais avez-vous déjà entendu dire que quelqu'un avait des problèmes pour ouvrir ces sites Web?

Asterisk
http://wayback.archive.org/web/*/http://google.com

Colon
https://en.wikipedia.org/wiki/Wikipedia:A propos

Plus
https://plus.google.com/+google

Au signe, deux points, virgule et point d'exclamation
https: //www.google.com/maps/place/USA/@36.2218457, ...

Pour cette raison, ces caractères devraient être utilisables non codés sans problème. Bien sûr, vous ne devriez pas utiliser à &;cause de séquences d'encodage comme &amp;. La même raison est valable pour %celle utilisée pour encoder les caractères en général. Et =comme il attribue une valeur à un nom de paramètre.

Enfin, je dirais que c'est correct d'utiliser ces non encodés:

0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_~!+,*:@

Mais si vous vous attendez à des URL générées de manière aléatoire, vous ne devez pas les utiliser .!, car elles marquent la fin d'une phrase et certaines applications de messagerie ne lieront pas automatiquement le dernier caractère de l'URL. Exemple:

Visit http://example.com/foo=bar! !
mgutt
la source
Approche pratique - bon travail. Je cherchais votre dernière liste - le +signe en particulier :-D
Oliver
12

D' ici

Ainsi, seuls les caractères alphanumériques, les caractères spéciaux $-_.+!*'(), et les caractères réservés utilisés à leurs fins réservées peuvent être utilisés non codés dans une URL.

AdaTheDev
la source
6

RFC3986 définit deux jeux de caractères que vous pouvez utiliser dans un URI:

  • Caractères réservés ::/?#[]@!$&'()*+,;=

    reserved = gen-delims / sub-delims

    gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"

    sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="

    Le but des caractères réservés est de fournir un ensemble de caractères de délimitation qui se distinguent des autres données dans un URI. Les URI qui diffèrent dans le remplacement d'un caractère réservé par l'octet codé en pourcentage correspondant ne sont pas équivalents.

  • Caractères non réservés :A-Za-z0-9-_.~

    non réservé = ALPHA / DIGIT / "-" / "." / "_" / "~"

    Les caractères autorisés dans un URI mais n'ayant pas de fonction réservée sont appelés non réservés.

Cyker
la source
3

Le changement à venir concerne les noms de domaine chinois et arabes et non les URI. Les URI internationalisés sont appelés IRI et sont définis dans la RFC 3987 . Cependant, cela dit, je recommanderais de ne pas le faire vous-même, mais de compter sur une bibliothèque existante et testée car il existe de nombreux choix d'encodage / décodage URI et de ce qui est considéré comme sûr par spécification, par rapport à ce qui est sûr par une utilisation réelle (navigateurs) .

Dajobe
la source
0

Si vous souhaitez offrir une expérience particulière aux utilisateurs, vous pouvez utiliser pushStatepour apporter un large éventail de caractères à l'URL du navigateur:

entrez la description de l'image ici

var u="";var tt=168;
for(var i=0; i< 250;i++){
 var x = i+250*tt;
console.log(x);
 var c = String.fromCharCode(x);
 u+=c; 
}
history.pushState({},"",250*tt+u);
Sinistre
la source