URL中允许使用方括号吗?

60

URL中是否允许方括号?

我注意到Apache commons HttpClient(3.0.1)会抛出IOException,但wget和Firefox支持方括号。

URL示例:

http://example.com/path/to/file[3].html

我的HTTP客户端遇到了这样的URL,但我不确定是要修补代码还是抛出异常(实际上应该是抛出异常)。


Firefox在地址栏中显示用户友好的URL,但它实际发送的URL已经编码了特殊字符。 - DJDaveMark
许多版本的WordPress和Magento使用未编码的方括号,因此如果您正在制作客户端,我建议仅发出警告或消息级别的问题。最终,您应该假设应用程序开发人员不会为您提供原始输入,并且您不希望依赖于当前仅取决于应用程序选择的网关的行为。 - That Realty Programmer Guy
10个回答

62

RFC 3986指出:

标识为Internet协议字面地址的主机,版本6 [RFC3513] 或更高版本,应该使用方括号(“[”和“]”)将IP字面值包含在内以进行区分。这是URI语法中允许使用方括号字符的唯一位置。

因此理论上您不应该在实际应用中看到这样的URI,因为它们应该被编码后再发送。


许多框架实际上在未编码的情况下在程序中使用它们。尤其是在查询字符串中,但不仅限于此。 - That Realty Programmer Guy

28

URL中的方括号[]通常不被支持。

请使用%5B%5D代替它们:

  • 使用命令行,以下示例基于bashsed

url='http://example.com?day=[0-3][0-9]'
encoded_url="$( sed 's/\[/%5B/g;s/]/%5D/g' <<< "$url")"
  • 使用 Java URLEncoder.encode(String s, String enc) 方法。

  • 使用 PHP 的 rawurlencode()urlencode() 函数。

  • <?php
    echo '<a href="http://example.com/day/',
        rawurlencode('[0-3][0-9]'), '">';
    ?>
    

    输出:

    <a href="http://example.com/day/%5B0-3%5D%5B0-9%5D">
    
    或者:
    <?php
    $query_string = 'day=' . urlencode('[0-3][0-9]') .
                    '&month=' . urlencode('[0-1][0-9]');
    echo '<a href="http://example.com?',
          htmlentities($query_string), '">';
    ?>
    
  • 使用你最喜欢的编程语言...请通过发表评论或直接编辑此答案来添加你从编程语言中使用的函数;-)

  • 有关详细信息,请参见RFC 3986,指定URL语法。附录A为查询字符串中的%-encoding(方括号属于“gen-delims”,应%-encoded)。


    2
    请支持“通常不支持”的说法,经过相当广泛的测试,这似乎非常不正确。 - That Realty Programmer Guy

    15

    我知道这个问题有点老了,但我想指出PHP使用方括号在URL中传递数组。

    http://www.example.com/foo.php?bar[]=1&bar[]=2&bar[]=3
    
    在这种情况下,$_GET ['bar']将包含array(1,2,3)

    18
    没问题,但是当浏览器不会自动进行编码时,仍然需要对它们进行编码。PHP仍然可以正确解释括号,并且它自己的http_build_query()函数也会对它们进行编码。 - Wilco
    @Wilco 除了个人观点之外,许多 PHP 框架都没有对它们进行编码。 - That Realty Programmer Guy

    5
    几乎唯一不允许出现在路径名中的字符是 # 和 ?,因为它们表示路径的结尾。
    URI RFC 将有明确的答案:

    http://www.ietf.org/rfc/rfc1738.txt

    不安全的字符:

    字符可能因为多种原因而不安全。空格字符是不安全的,因为当URL被转录、排版或经过文字处理程序处理时,重要的空格可能会消失,而无关紧要的空格可能会引入。"<"和">"字符是不安全的,因为它们在自由文本中用作URL周围的分隔符; 引号(""")用于在某些系统中分隔URL。"#"字符是不安全的,并且应始终进行编码,因为它在万维网和其他系统中用于将URL与可能跟随其后的片段/锚点标识符分隔开来。百分号("%")字符是不安全的,因为它用于对其他字符进行编码。其他字符也是不安全的,因为网关和其他传输代理有时已知会修改这些字符。这些字符包括"{", "}", "|", "\", "^", "~", "[", "]", 和 "`"。

    所有不安全的字符必须始终在URL中进行编码。例如,即使在不通常处理片段或锚点标识符的系统中,"#"字符也必须在URL中进行编码,以便如果将URL复制到使用它们的另一个系统中,就不需要更改URL编码。

    答案是它们应该进行十六进制编码,但根据波斯特尔法则,大多数情况下都可以直接接受它们。

    7
    所有不安全的字符在URL中必须始终进行编码。这是“必须(MUST)”而不是“应该(SHOULD)”。 - plaugg
    @plaugg 客户端存在于现实世界中,这个答案的“应该”也是如此——而规范存在于一个正式的信息系统中。也就是说,为了符合规范,是必须对它们进行编码的。然而在现实中,人们只能提出一个意见,即你应该对它们进行编码,因为它们在一般情况下可以正常工作。事实上,规范应该被修改以反映使用情况。 - That Realty Programmer Guy

    5
    任何接受URL且不在引入特殊字符时抛出异常的浏览器或网络软件几乎肯定会在幕后对特殊字符进行编码。花括号、方括号、空格等都有特殊的编码方式,以避免产生冲突。根据之前的答案,处理这些字符的最安全方法是在将它们交给尝试解析URL的东西之前对它们进行URL编码。

    这适用于空格和其他特殊字符,但不适用于方括号。当我在地址栏中输入 https://www.example.com/?a[]=1 时,我看到方括号在HTTP中未经转义地发送。 - Franklin Yu
    1
    Chrome(98)和Firefox(97)无法对 [ 和 ] 字符进行编码。 - Olivier Masseau

    2

    7
    我相信你看到的是浏览器将它们作为输入接受了。然而,如果你在 Stackoverflow 的结果页面上点击其中一个标签,它会对括号进行编码...search?tab=newest&q=square%20brackets%20%5burl%5d - Feckmore
    2
    我检查了请求头和位置文本,它们在Chrome中没有被编码。我们需要进行什么样的测试才能确定它们是否被“容忍”? - QueueHammer

    2

    如果要使用HttpClient常见类,您需要查看org.apache.commons.httpclient.util.URIUtil类,特别是encode()方法。在尝试获取URL之前,请使用该方法对URL进行URI编码。


    1

    方括号被认为是不安全的,但大多数浏览器仍然可以正确解析。尽管如此,最好用其他字符替换方括号。


    问题在于,大多数浏览器根本不对方括号进行编码。 - Olivier Masseau

    1
    最好对它们进行URL编码,因为它们显然并不支持所有的Web服务器。有时,即使存在标准,也不是每个人都遵循它。

    1
    根据URL规范,方括号不是有效的URL字符。
    以下是相关片段:

    “国家”和“标点符号”字符不出现在任何生产中,因此可能不会出现在URL中。
    国家 { | } | vline | [ | ] | \ | ^ | ~
    标点符号 < | >


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接