哪些字符使URL无效?

这些url是否有效?

example.com/file [/] . html http://example.com/file [/] . html


当前回答

在这个例子中,“[”和“]”是“不明智的”字符,但仍然是合法的。如果[]中的'/'是文件名的一部分,那么它是无效的,因为'/'是保留的,应该正确编码:

http://example.com/file[/].html

为了澄清并直接解决上面的问题,有几种类型的字符会导致url和uri出现问题。

There are some characters that are disallowed and should never appear in a URL/URI, reserved characters (described below), and other characters that may cause problems in some cases, but are marked as "unwise" or "unsafe". Explanations for why the characters are restricted are clearly spelled out in RFC-1738 (URLs) and RFC-2396 (URIs). Note the newer RFC-3986 (update to RFC-1738) defines the construction of what characters are allowed in a given context but the older spec offers a simpler and more general description of which characters are not allowed with the following rules.

URI语法中不允许的US-ASCII字符:

   control     = <US-ASCII coded characters 00-1F and 7F hexadecimal>
   space       = <US-ASCII coded character 20 hexadecimal>
   delims      = "<" | ">" | "#" | "%" | <">

字符“#”被排除在外,因为它用于将URI与片段标识符分隔开来。百分比字符“%”被排除,因为它用于转义字符的编码。换句话说,“#”和“%”是保留字符,必须在特定的上下文中使用。

不明智的字符列表是允许的,但可能会导致问题:

   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

uri和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。

其他回答

一些Unicode字符范围是有效的HTML5,尽管使用它们可能仍然不是一个好主意。

例如,href文档说http://www.w3.org/TR/html5/links.html#attr-hyperlink-href:

a和area元素上的href属性必须具有一个有效的URL值,该值可能被空格包围。

那么“有效URL”的定义指向http://url.spec.whatwg.org/,它说它的目标是:

将RFC 3986和RFC 3987与当代实现对齐,并在此过程中淘汰它们。

该文档将URL代码点定义为:

ASCII alphanumeric, "!", "$", "&", "'", "(", ")", "*", "+", ",", "-", ".", "/", ":", ";", "=", "?", "@", "_", "~", and code points in the ranges U+00A0 to U+D7FF, U+E000 to U+FDCF, U+FDF0 to U+FFFD, U+10000 to U+1FFFD, U+20000 to U+2FFFD, U+30000 to U+3FFFD, U+40000 to U+4FFFD, U+50000 to U+5FFFD, U+60000 to U+6FFFD, U+70000 to U+7FFFD, U+80000 to U+8FFFD, U+90000 to U+9FFFD, U+A0000 to U+AFFFD, U+B0000 to U+BFFFD, U+C0000 to U+CFFFD, U+D0000 to U+DFFFD, U+E1000 to U+EFFFD, U+F0000 to U+FFFFD, U+100000 to U+10FFFD.

然后在语句中使用术语“URL代码点”:

如果c不是URL代码点,也不是“%”,解析错误。

在解析算法的几个部分,包括模式,权限,相对路径,查询和片段状态:所以基本上是整个URL。

同样,验证器http://validator.w3.org/会通过“你好”这样的url,而不会通过像空格“a b”这样的字符的url

当然,正如Stephen C所提到的,这不仅与字符有关,还与上下文有关:你必须理解整个算法。但由于类“URL代码点”用于算法的关键点,它提供了一个很好的想法,你可以使用或不使用。

请参见:url中的Unicode字符

大多数现有的答案都是不切实际的,因为它们完全忽略了地址在现实世界中的用法,比如:

https://en.wikipedia.org/wiki/Mobius_strip or https://zh.wikipedia.org/wiki/Wikipedia: about the Chinese wikipedia/en.

首先,进入术语。这些地址是什么?它们是有效的url吗?

从历史上看,答案是“不”。根据RFC 3986,从2005年开始,这样的地址不是uri(因此也不是url,因为url是uri的一种)。根据2005 IETF标准的术语,我们应该正确地称它们为IRI(国际化资源标识符),如RFC 3987中定义的那样,它们在技术上不是uri,但可以通过简单地对IRI中的所有非ascii字符进行百分比编码来转换为uri。

根据现代规范,答案是“是的”。WHATWG生活标准简单地将以前被称为“uri”或“iri”的东西归类为“url”。这使规范术语与没有阅读规范的普通人使用“URL”这个词的方式保持一致,这是规范的目标之一。

WHATWG生活标准下允许哪些角色?

根据“URL”的新含义,允许使用哪些字符?在URL的许多部分,例如查询字符串和路径,我们被允许使用任意的“URL单位”,它们是

URL代码点和百分比编码的字节。

什么是“URL代码点”?

URL代码点是ASCII字母数字,U+0021 (!), U+0024 ($), U+0026 (&), U+0027 ('), U+0028左括号,U+0029右括号,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(~),以及U+00A0到U+10FFFD范围内的代码点,包括,不包括代理和非字符。

(请注意,“URL代码点”列表不包括%,但如果%s是百分比编码序列的一部分,则允许在“URL代码单位”中使用%s。)

我能发现的唯一一个规范允许使用不在这个集合中的任何字符的地方是在主机中,其中IPv6地址包含在[和]字符中。URL中的其他地方,要么允许URL单位,要么使用一些更严格的字符集。

旧的rfc允许哪些字符?

出于历史的考虑,由于在这里的答案中没有充分探讨,让我们检查一下旧眼镜下允许的情况。

首先,我们有两种类型的RFC 3986保留字符:

: / ?#[]@,它们是RFC 3986中定义的URI的通用语法的一部分 !$&'()*+,;=,它们不是RFC通用语法的一部分,而是保留用于特定URI方案的语法组件。例如,分号和逗号被用作数据uri语法的一部分,&和=被用作查询字符串中普遍存在的?foo=bar&qux=baz格式的一部分(RFC 3986没有指定)。

上面的任何保留字符都可以在URI中合法地使用而不进行编码,可以用于它们的语法目的,也可以作为数据中的文字字符,在某些地方这样的使用不会被误解为用于其语法目的的字符。(例如,尽管/在URL中具有语法意义,但您可以在查询字符串中使用它,因为它在查询字符串中没有意义。)

RFC 3986还指定了一些无保留字符,它们总是可以简单地用来表示没有任何编码的数据:

abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 - _ ~

最后,允许%字符本身用于百分比编码。

这样就只留下以下ASCII字符被禁止出现在URL中:

控制字符(字符0-1F和7F),包括换行、制表符和回车符。 “< > ^ ' {|}

来自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编写后的十年中添加的。


最后,也许值得注意的是,仅仅知道哪些字符可以合法地出现在URL中还不足以识别某个给定的字符串是否是合法的URL,因为有些字符只在URL的特定部分合法。例如,保留字符[和]在像http://[1080::8:800:200C:417A]/foo这样的URL中作为IPv6字面主机的一部分是合法的,但在任何其他上下文中都是不合法的,因此OP的例子http://example.com/file[/].html是非法的。

来源(需要时加强调):

Unsafe: Characters can be unsafe for a number of reasons. The space character is unsafe because significant spaces may disappear and insignificant spaces may be introduced when URLs are transcribed or typeset or subjected to the treatment of word-processing programs. The characters "<" and ">" are unsafe because they are used as the delimiters around URLs in free text; the quote mark (""") is used to delimit URLs in some systems. The character "#" is unsafe and should always be encoded because it is used in World Wide Web and in other systems to delimit a URL from a fragment/anchor identifier that might follow it. The character "%" is unsafe because it is used for encodings of other characters. Other characters are unsafe because gateways and other transport agents are known to sometimes modify such characters. These characters are "{", "}", "|", "", "^", "~", "[", "]", and "`". All unsafe characters must always be encoded within a URL. For example, the character "#" must be encoded within URLs even in systems that do not normally deal with fragment or anchor identifiers, so that if the URL is copied into another system that does use them, it will not be necessary to change the URL encoding. Source

我提出了一些PHP正则表达式,可以将文本中的url转换为锚标记。(首先它转换所有的www。url到http://,,然后转换所有的url与https?:// to a href=…HTML链接

美元管柱= preg_replace (' / (https ?:\/\/)([!#$&-;=?\-\[\]_ a - z ~ %] +) / sim’,'“$ 1 $ 2”< a href = > $ 2 < / a > ', preg_replace(' /(±s) ( \.)([!#$&-;=?\-\[\]_ a - z ~ %] +) / sim’' $ 1http: / / $, $管柱));

通常,RFC 3986定义的uri(参见章节2:字符)可以包含以下84个字符中的任意一个:

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

注意,这个列表没有说明这些字符可能出现在URI中的哪个位置。

任何其他字符都需要使用百分比编码(%hh)进行编码。URI的每个部分对于百分比编码的单词需要表示哪些字符有进一步的限制。