2024-12-01 10:00:01

URL中允许的字符

有人知道可以在GET中使用而不经过编码的完整字符列表吗?目前我使用A-Z - A-Z和0-9…但我想知道完整的名单。

我也感兴趣的是,是否会发布关于即将添加中文、阿拉伯语url的规范(显然这将对我的问题产生很大影响)。


当前回答

我测试它通过请求我的网站(apache)与所有可用的字符在我的德语键盘作为URL参数:

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

这些没有被编码:

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

urlencode()后未编码:

0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_

rawurlencode()后未编码:

0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_~

注意:在PHP 5.3.0之前,rawurlencode()编码~,因为RFC 1738。但它被RFC 3986所取代,所以现在可以安全使用了。但我不明白为什么{}是通过rawurlencode()编码的,因为RFC 3986中没有提到它们。

我做的另一个测试是关于邮件文本中的自动链接。我测试了Mozilla Thunderbird, aol.com, outlook.com, gmail.com, gmx.de和yahoo.de,他们完全链接包含这些字符的url:

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

当然?也有联系,但只有用过一次。

有些人现在建议只使用rawurlencode()字符,但您是否听说过有人在打开这些网站时遇到问题?

星号 http://wayback.archive.org/web/ * / http://google.com

结肠 https://en.wikipedia.org/wiki/Wikipedia:About

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

@号,冒号,逗号和感叹号 https://www.google.com/maps/place/USA/@36.2218457,…

正因为如此,这些字符应该可以在没有编码的情况下使用。当然你不应该使用&;因为编码序列像&。同样的原因也适用于%,因为它通常用于编码字符。和=,因为它为参数名赋值。

最后,我想说的是,可以使用这些未编码的:

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

但如果你希望随机生成url,你不应该使用标点符号。!,因为一些邮件应用程序不会自动链接它们:

http://example.com/?foo=bar !<最后一个字符未链接

其他回答

这个答案讨论了字符可以包含在URL片段部分中而不进行转义。我单独发布了一个答案,因为这部分与这里的其他优秀答案略有不同(并且可以结合使用)。

片段部分不会被发送到服务器,在这个例子中,它是在#后面的字符:

https://example.com/#STUFF-HERE

规范

RFC 3986中的相关规范为:

  fragment    = *( pchar / "/" / "?" )
  pchar       = unreserved / pct-encoded / sub-delims / ":" / "@"
  unreserved  = ALPHA / DIGIT / "-" / "." / "_" / "~"
  sub-delims  = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="

这也引用了RFC 2234中的规则

  ALPHA       =  %x41-5A / %x61-7A   ; A-Z / a-z
  DIGIT       =  %x30-39             ; 0-9

结果

所以完整的列表,不包括转义(pct编码)是:

A-Z -z 0-9。_ ~ !$ & ' () * +,;=: @ / ?

为了方便起见,这里有一个匹配有效的、未转义的片段的PCRE表达式:

/^[A-Za-z0-9\-._~!$&'()*+,;=:@\/?]*$/

编码

算起来,有:

26 + 26 + 10 + 19 = 81代码点

您可以使用基数81来有效地编码这里的数据。

如果你想给用户一种特殊的体验,你可以使用pushState将各种字符带到浏览器的url:

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);

我测试它通过请求我的网站(apache)与所有可用的字符在我的德语键盘作为URL参数:

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

这些没有被编码:

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

urlencode()后未编码:

0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_

rawurlencode()后未编码:

0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_~

注意:在PHP 5.3.0之前,rawurlencode()编码~,因为RFC 1738。但它被RFC 3986所取代,所以现在可以安全使用了。但我不明白为什么{}是通过rawurlencode()编码的,因为RFC 3986中没有提到它们。

我做的另一个测试是关于邮件文本中的自动链接。我测试了Mozilla Thunderbird, aol.com, outlook.com, gmail.com, gmx.de和yahoo.de,他们完全链接包含这些字符的url:

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

当然?也有联系,但只有用过一次。

有些人现在建议只使用rawurlencode()字符,但您是否听说过有人在打开这些网站时遇到问题?

星号 http://wayback.archive.org/web/ * / http://google.com

结肠 https://en.wikipedia.org/wiki/Wikipedia:About

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

@号,冒号,逗号和感叹号 https://www.google.com/maps/place/USA/@36.2218457,…

正因为如此,这些字符应该可以在没有编码的情况下使用。当然你不应该使用&;因为编码序列像&。同样的原因也适用于%,因为它通常用于编码字符。和=,因为它为参数名赋值。

最后,我想说的是,可以使用这些未编码的:

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

但如果你希望随机生成url,你不应该使用标点符号。!,因为一些邮件应用程序不会自动链接它们:

http://example.com/?foo=bar !<最后一个字符未链接

RFC3986定义了两组你可以在URI中使用的字符:

Reserved Characters: :/?#[]@!$&'()*+,;= reserved = gen-delims / sub-delims gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" The purpose of reserved characters is to provide a set of delimiting characters that are distinguishable from other data within a URI. URIs that differ in the replacement of a reserved character with its corresponding percent-encoded octet are not equivalent. Unreserved Characters: A-Za-z0-9-_.~ unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" Characters that are allowed in a URI but do not have a reserved purpose are called unreserved.

66个无保留字符的完整列表在RFC3986中,请访问:https://www.rfc-editor.org/rfc/rfc3986#section-2.3

这是以下正则表达式集中的任何字符:

[A-Za-z0-9_.\-~]