哪些字符使网址无效?
哪些字符使网址无效?
这些有效的网址是?
example.com/file[/].html
http://example.com/file[/].html
通常,由RFC 3986定义的URI(参见第2节:字符)可能包含以下任何字符:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:/?#[]@!$&'()*+,;=`.
任何其他字符都需要使用百分号编码( %
hh
)进行编码。 URI的每个部分都对哪些字符需要用百分比编码的字表示进一步限制。
要添加一些说明并直接解决上述问题,有几种类型的字符会导致URL和URI出现问题。
有些字符是不允许的,不应出现在URL / URI,保留字符(如下所述)和其他字符中,这些字符在某些情况下可能会导致问题,但会被标记为“不明智”或“不安全”。 RFC-1738(URL)和RFC-2396(URI)明确阐述了字符限制原因的解释。 请注意,较新的RFC-3986(更新到RFC-1738)定义了在给定上下文中允许使用什么字符的构造,但旧规范提供了对不允许使用哪些字符的更简单更一般的描述。
排除的US-ASCII字符在URI语法中不允许使用:
control = <US-ASCII coded characters 00-1F and 7F hexadecimal>
space = <US-ASCII coded character 20 hexadecimal>
delims = "<" | ">" | "#" | "%" | <">
不明字符列表被允许但可能会导致问题:
unwise = "{" | "}" | "|" | "" | "^" | "[" | "]" | "`"
以下字符在查询组件中保留并且在URI / URL中具有特殊含义:
reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","
上面的“保留”语法类是指URI内允许使用的那些字符,但在通用URI语法的特定组件中可能不允许使用这些字符。 “保留”集中的字符不保留在所有上下文中 。 例如,主机名可以包含一个可选的用户名,因此它可能类似于ftp://user@hostname/
,其中'@'字符具有特殊含义。
下面是一个包含无效和不明智字符(例如'$','[',']')并且应该被正确编码的URL的例子:
http://mw1.google.com/mw-earth-vectordb/kml-samples/gp/seattle/gigapxl/$[level]/r$[y]_c$[x].jpg
URIs / URL的一些字符限制依赖于编程语言。 例如,'|' (0x7C)字符,但只有在URI规范中标记为“不明智”才会在Java java.net.URI构造函数中引发URISyntaxException,因此像http://api.google.com/q?exp=a|b
这样的URL是如果将Java与URI对象实例一起使用,则不得将其编码为http://api.google.com/q?exp=a%7Cb
。
现有的大多数答案都是不切实际的,因为他们完全忽略了地址的实际使用情况,例如:
好的,根据RFC 3986,这些地址不是URI(因此URL不是URL,因为URL是一种URI)。 如果我们认为自己遵守现有IETF标准的术语,那么我们应该正确地称它们为RFC 3987中定义的IRI(国际化资源标识符),它们在技术上不是URI,但可以简单地通过百分比编码转换为URI IRI中的-ASCII字符。 但是,普通人从来没有听说过IRI,只是简单地调用这些URI或URL(实际上,目前正在开展一项WHATWG工作来创建一个新的更广泛的URL规范,将所有“URI”和“IRI”简单地归类为“URL”与现代世界中这些术语的现代用法)。
假设我们想立即采用URL的这种含义(这与IETF规范不一致,但将我们与日常使用对齐)。 在这种情况下,哪些字符在URL中有效?
首先,我们有两种类型的RFC 3986保留字符:
:/?#[]@
,它们是RFC 3986中定义的URI的通用语法的一部分 !$&'()*+,;=
,它们不是RFC通用语法的一部分,但保留用作特定URI方案的语法组件。 例如,分号和逗号用作数据URI语法的一部分, &
和=
用作查询字符串中普遍存在的?foo=bar&qux=baz
格式的一部分(RFC 3986未指定)。 上述任何保留字符都可以在没有编码的情况下在URI中合法使用,既可以用于其语法目的,也可以用作某些地方数据中的文字字符,这些字符不能被误解为用于其语法目的的字符。 (例如,尽管/
在URL中具有语法含义,但您可以在查询字符串中将其用于未编码,因为它在查询字符串中没有含义。)
RFC 3986还指定了一些未保留的字符,它们可以始终用于简单地表示没有任何编码的数据:
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~
最后,百分号编码允许%
字符本身。
只留下禁止出现在URL中的以下ASCII字符:
"<>^`{|}
来自ASCII的其他每个字符都可以在URL中合法地显示。
然后RFC 3987扩展了那些具有以下unicode字符范围的未预留字符集:
%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
但是鉴于最新的Unicode块定义,这些块选择显得离奇而随意。 这可能是因为自RFC 3987编写以来,这些块已添加到了十年。 WhatWG的进行中的规格有一个更慷慨的名单:
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 + U + F0000到U + FFFFD,U + B0000到U + BFFFD,U + C0000到U + CFFFD,U + D0000到U + DFFFD,U + E0000到U + EFFFD,U + F0000到U + 10FFFD
当然,应该注意的是,只要知道哪些字符可以合法地出现在URL中就不足以识别某个给定的字符串是否是合法的URL,因为某些字符仅在URL的特定部分合法。 例如,保留字符[
和]
在http:// [1080 :: 8:800:200C:417A] / foo等URL中作为IPv6文字主机的一部分是合法的,但在任何其他上下文中都不合法,所以OP的http://example.com/file[/].html
的例子是非法的。