Answers:
根据RFC 1738规范:
因此,仅字母数字,特殊字符“
$-_.+!*'(),
”和用于保留目的的保留字符可以在URL中未经编码地使用。
编辑:正如@Jukka K. Korpela正确指出的那样,此RFC由RFC 3986更新。这已经扩展并阐明了对主机有效的字符,很遗憾,它不容易复制和粘贴,但我会尽力而为。
按照第一个匹配的顺序:
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
A-Za-z0-9_.-~
在此答案的开头添加未保留和保留字符的列表。!*'();:@&=+$,/?#[]
它可以为人们节省时间
reserved = gen-delims / sub-delims gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
URI中允许的字符是保留的还是不保留的(或作为百分号编码的一部分的百分号)
http://en.wikipedia.org/wiki/Percent-encoding#Types_of_URI_characters
表示这些是RFC 3986非 保留字符(第2.3节)以及保留字符(第2.2节)(如果它们需要保留其特殊含义)。以及百分比字符作为百分比编码的一部分。
The characters allowed in a URI are either reserved or unreserved (or a percent character as part of a percent-encoding)
66个未保留字符的完整列表在RFC3986中,在这里:http ://tools.ietf.org/html/rfc3986#section-2.3
这是以下正则表达式集中的任何字符:
[A-Za-z0-9_.\-~]
{}^\~
和backtick
不安全。由于文件系统,RFC3986列出\为不安全。这{}^
也可以使用。
-
或将其放在字符类的开头或结尾,因为[.-~]
实际上它包含从46到126的所有ASCII字符
我通过请求我的网站(apache)并使用德语键盘上所有可用字符作为URL参数进行了测试:
http://example.com/?^1234567890ß´qwertzuiopü+asdfghjklöä#<yxcvbnm,.-°!"§$%&/()=? `QWERTZUIOPÜ*ASDFGHJKLÖÄ\'>YXCVBNM;:_²³{[]}\|µ@€~
这些未编码:
^0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,.-!/()=?`*;:_{}[]\|~
之后未编码urlencode()
:
0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_
之后未编码rawurlencode()
:
0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_~
注意:由于RFC 1738而在PHP 5.3.0之前rawurlencode()
编码。但这已被RFC 3986取代,因此现在可以安全使用。但是我不明白为什么要对它们进行编码,因为RFC 3986中没有提到它们。~
{}
rawurlencode()
我进行的另一项测试是关于邮件文本中的自动链接。我测试了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:关于
加号
https://plus.google.com/+google
标有冒号,逗号和感叹号的符号为
https://www.google.com/maps/place/USA/@36.2218457,...
因此,这些字符应该可以未经编码地使用而不会出现问题。当然,&;
由于编码序列如,您不应该使用&
。相同的原因同样适用,%
因为它通常用于编码char。并=
为参数名称分配一个值。
最后,我想说可以使用这些未编码的代码:
0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_~!+,*:@
但是,如果您希望使用随机生成的URL,则不应使用.!
,因为这些URL 标记了句子的结尾,并且某些邮件应用程序不会自动链接该URL的最后一个字符。例:
Visit http://example.com/foo=bar! !
+
特别是这个标志:-D
这些在RFC3986中列出。请参阅Collected ABNF for URI, 以了解在何处允许使用什么以及用于解析/验证的正则表达式。
RFC3986定义了可以在URI中使用的两组字符:
保留字符::/?#[]@!$&'()*+,;=
保留= gen-delims / sub-delims
gen-delims =“:” /“ /” /“?” /“#” /“ [” /“]” /“ @”
sub-delims =“!” /“ $” /“&” /“'” /“(” /“)” /“ *” /“ +” /“,” /“;” /“ =”
保留字符的目的是提供一组与URI中的其他数据区分开的定界字符。在保留字符替换为其相应的百分比编码八位字节方面有所不同的URI不等效。
未保留的字符:A-Za-z0-9-_.~
未保留= ALPHA / DIGIT /“-” /“。/“ _” /“〜”
URI中允许但没有保留用途的字符称为未保留字符。
!*'();:@&=+$,/?#[]
还是不保留的A-Za-z0-9_.~-
(或%
作为百分比编码一部分的百分比字符)