哪些字符使URL无效?

哪些字符使URL无效?

这些url是否有效?

  • # EYZ0
  • # EYZ0
637408 次浏览

这并不是对你的问题的真正答案,但验证URL确实是一个严肃的p.i.t.a。你可能最好验证域名,并留下URL的查询部分。这是我的经验。

您还可以通过ping URL来查看它是否会得到一个有效的响应,但是对于这样一个简单的任务来说,这可能有点太过了。

正则表达式检测url是丰富的,谷歌它:)

URI中可以使用的所有有效的字符(URLURI的一种类型)都在RFC 3986中定义。

所有其他字符都可以在URL中使用,只要它们是“URL编码”的。第一。这包括为特定的“代码”更改无效字符;(通常以百分号(%)后面跟着一个十六进制数的形式)。

这个链接HTML URL编码参考包含一个无效字符的编码列表。

一般来说,由RFC 3986(参见第二节人物)定义的uri可能包含以下84个字符中的任何一个:

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

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

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

在你的补充问题中,你问www.example.com/file[/].html是否是一个有效的URL。

该URL是无效的,因为URL是一种URI类型,而有效的URI必须具有像http:这样的方案(请参阅RFC 3986)。

如果你想问http://www.example.com/file[/].html是否是一个有效的URL,那么答案仍然是否定的,因为方括号字符在那里是无效的。

方括号字符为如下格式的url保留:http://[2001:db8:85a3::8a2e:370:7334]/foo/bar(即IPv6文字而不是主机名)

如果您想全面理解这个问题,值得仔细阅读RFC 3986。

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

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

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

有一些字符是不允许的,永远不应该出现在URL/URI中,保留字符(如下所述),以及其他在某些情况下可能导致问题的字符,但被标记为“不明智的”。或“;unsafe"。在rfc - 1738 (url)和rfc - 2396 (uri)中清楚地解释了为什么字符被限制。请注意,更新的rfc - 3986 (RFC-1738的更新)定义了在给定上下文中允许哪些字符的结构,但旧的规范提供了一个更简单和更通用的描述,哪些字符不允许使用以下规则。

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    = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","

“reserved"上面的语法类指的是在URI中允许的字符,但在通用URI语法的特定组件中可能不允许这些字符。# EYZ1。例如,主机名可以包含一个可选的用户名,所以它可以是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

我需要选择字符来分割字符串中的URL,所以我决定创建一个字符列表,这些字符无法在URL中自己找到:

>>> allowed = "-_.~!*'();:@&=+$,/?%#[]?@ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
>>> from string import printable
>>> ''.join(set(printable).difference(set(allowed)))
'`" <\x0b\n\r\x0c\\\t{^}|>'

所以,可能的选择是换行符,制表符,空格,反斜杠和"<>{}^|。我想我还是用空格或者换行吧。:)

一些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字母数字、“!”、“$”、“&”、“'”、“(”、“)”、“*”、“+”、“-”、“。”、“/”、“:”、“;”、“=”、“?”、“=”、“?”、“@”、“_”、“~”、“U+FDF0 ~ U+FFFD、U+10000 ~ U+1FFFD、U+20000 ~ U+2FFFD、U+30000 ~ U+3FFFD、U+40000 ~ U+5FFFD、U+60000 ~ U+6FFFD、U+70000 ~ U+7FFFD、U+80000 ~ U+8FFFD、U+90000 ~ U+9FFFD、U+A0000 ~ U+AFFFD、U+B0000 ~ U+BFFFD、U+C0000 ~ U+CFFFD、U+D0000 ~ U+DFFFD、U+E1000 ~ U+EFFFD、U+F0000到U+FFFFD, U+100000到U+10FFFD。

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

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

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

此外,验证器http://validator.w3.org/会传递像"你好"这样的url,而不会传递像"a b"这样的空格字符

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

参见:url中的Unicode字符

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

  • # EYZ0或
  • # EYZ0。

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

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

根据现代规范,答案是“是”。WHATWG生活水平简单地分类了以前被称为“uri”的所有内容;或“;IRIs"作为“URLs"。这使规范术语与没有阅读规范的普通人使用的单词“url”保持一致,这是规范的目标之一。

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

根据“url”的新含义,允许使用哪些字符?在URL的许多部分,例如查询字符串和路径,我们可以使用任意的“URL units",这是

URL编码点percent-encoded字节

什么是“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代码点”列表;不包括%,但%被允许在“URL代码单元”中;如果它们是百分比编码序列的一部分。)

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

旧的rfc允许哪些字符?

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

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

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

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

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

  • # EYZ0

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

这样URL中只会出现被禁止的的ASCII字符:

  • 控制字符(字符0-1F和7F),包括换行、制表符和回车符。
  • # EYZ0

来自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是非法的。

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

# EYZ0

我正在实现一个旧的HTTP(0.9, 1.0, 1.1)请求和响应读取器/写入器。请求URI是最有问题的地方。

你不能只使用RFC 1738、2396或3986。有许多旧的HTTP客户端和服务器允许更多的字符。所以我根据意外发布的web服务器访问日志进行了研究:"GET URI HTTP/1.0" 200

我发现在uri中经常使用以下非标准字符:

\ { } < > | ` ^ "

这些字符在RFC 1738中被描述为不安全的

如果你想兼容所有旧的HTTP客户端和服务器,你必须在请求URI中使用允许这些字符

请在oghttp-request-collector中阅读有关这项研究的更多信息。

我不能评论以上的答案,但我想强调的是,并非所有地方都允许使用允许的字符。例如,域名不能有下划线,因此http://test_url.com无效。

来源(需要时加强调):

不安全:

字符不安全的原因有很多。空格字符是不安全的,因为当url被转录或排版或受到文字处理程序的处理时,重要的空格可能会消失,而不重要的空格可能会引入。

字母"<"“和“;;是不安全的,因为它们被用作 自由文本中url周围的分隔符;引号(&;"")是用来 在一些系统中分隔url。字符"#"是不安全的和应该 总是被编码,因为它被用于万维网和其他 系统将URL与片段/锚标识符分隔开来 跟随它。字符"%"是不安全的,因为它用于 其他字符的编码。# EYZ0因为 众所周知,网关和其他传输代理有时会对此进行修改 字符。这些字符<强>“{“、“}”、“|“““,“^”、“~”、“(“, "]"和".

.

.

所有不安全字符必须始终编码在URL中。为 例如,字符"#"必须在url中编码,甚至在系统中 通常不处理片段或锚标识符,所以 如果URL被复制到另一个使用它们的系统中,它就会 不需要更改URL编码。 # EYZ0 < / p >