分号作为 URL 查询分隔符

Semicolon as URL query separator

提问人:mykhal 提问时间:8/14/2010 最后编辑:xnumadmykhal 更新时间:11/17/2023 访问量:52190

问:

尽管强烈建议(W3C 源,通过维基百科)让 Web 服务器支持分号作为 URL 查询项的分隔符(除了 & 号)(在撰写本文时,不再通过维基百科),但似乎并没有普遍遵循。

例如,比较

        http://www.google.com/search?q=nemo&oe=UTF-8

        http://www.google.com/search?q=nemo;OE=UTF-8

结果。(在后一种情况下,分号是或在撰写本文时被视为普通字符串字符,就好像 url 是:http://www.google.com/search?q=nemo%3Boe=utf-8)

尽管我尝试过的第一个 URL 解析库表现良好:

>>> from urlparse import urlparse, query_qs
>>> url = 'http://www.google.com/search?q=nemo;oe=utf-8'
>>> parse_qs(urlparse(url).query)
{'q': ['nemo'], 'oe': ['utf-8']}

接受分号作为分隔符的现状如何,潜在的问题或一些有趣的注释是什么?(从服务器和客户端的角度来看)

HTTP 解析 URL Web 服务器 查询字符串

评论

1赞 Brent Bradburn 12/5/2019
谷歌搜索只做了一件事,而Golang则反其道而行之:github.com/golang/go/issues/2210

答:

19赞 Daniel Vassallo 8/14/2010 #1

只要你的 HTTP 服务器和服务器端应用程序接受分号作为分隔符,你就应该可以开始了。我看不出任何缺点。正如你所说,W3C 规范站在你这边

我们建议 HTTP 服务器实现者,特别是 CGI 实现者支持使用 “;” 代替 “&”,以省去作者以这种方式转义 “&” 字符的麻烦。

评论

1赞 mykhal 8/14/2010
至少看到一个缺点 - 从客户的角度来看,我无法安全地决定使用而不是在请求中(好吧,我在问题中添加了从客户角度的提及);&
0赞 Daniel Vassallo 8/14/2010
@mykhal:“从客户的角度来看”......你的意思是当你通过 Web 服务或类似方式公开 API 时?因为否则,我认为通过 Web 浏览器使用网站的最终用户不应该关心。关于前者,是的,Web 服务消费者可能更习惯于使用 an,并且可能会对不寻常的约定感到困惑。&
0赞 mykhal 8/14/2010
@[Daniel Vassallo]我的意思是,一般来说。顺便说一句,我含蓄地解决了您在回答中提到的完全相同的 W3C 引用,因此这对我来说并不令人满意。没关系:)
19赞 Bob Aman 4/11/2013
有缺点。通过赋予 “;” 最初未在 RFC 中指定的特殊附加含义,可以强制在键和值文本中对 “;” 进行转义。例如。你会期望 ,但很可能最终会得到: 或其他一些值。那里有很多潜在的歧义。基本上,W3C 是愚蠢的。?q='one;two'&x=1{"q": "'one;two'", "x": "1"}{"q": "'one", "two'": null, "x": "1"}
1赞 Kyle Kelley 1/4/2014
在针对使用分号作为分隔符的 API (如 StackExchange API)进行测试时,您会怎么做
10赞 Matthias Fripp 7/12/2014 #2

我同意鲍勃·阿曼(Bob Aman)的观点。W3C 规范旨在使锚点超链接与看起来像 GET 请求形式的 URL 一起使用变得更加容易(例如,)。在这种情况下,与号与号与字符实体引用系统发生冲突,字符实体引用都以与号开头(例如,)。因此,W3C 建议 Web 服务器允许使用分号而不是与号作为字段分隔符,以便更轻松地编写这些 URL。但是,此解决方案要求编写者记住,必须用某些东西替换与号,并且 a 是一个同样有效的字段分隔符,即使 Web 浏览器在提交表单时普遍在 URL 中使用与号。可以说,这比记住在这些链接中用 an 替换 & 符号更困难,就像文档其他地方所做的那样。http://www.host.com/?x=1&y=2";&

更糟糕的是,在所有 Web 服务器都允许使用分号作为字段分隔符之前,URL 编写者只能将此快捷方式用于某些主机,而必须用于其他主机。如果给定主机停止允许分号分隔符,他们还必须稍后更改其代码。这当然比简单地使用 更难,这将永远适用于每台服务器。这反过来又消除了 Web 服务器允许使用分号作为字段分隔符的任何动机。当每个人都已经将 & 符号更改为 而不是 时,何必呢?&&&;

评论

0赞 Shawn Kovac 1/26/2016
我说,即使只使用&,而不允许两者兼而有之,也更难继续使用。我说让想要更简单生活的人使用;这将使他们更容易,以至于有时某些网站需要同时了解这两个选项的复杂性相对较少是值得的。
0赞 Shawn Kovac 1/26/2016
使用 & 分隔符处理 QueryStrings 比切换到 ; 复杂两倍多分隔 QueryString 项。用;大大减少了不正确地使用HTML内涵字符串以使用“&”的潜在错误。
0赞 Shawn Kovac 8/21/2019
我想我听到马蒂亚斯说,使用“&”作为分隔符更好,因为它们已经更受欢迎了。我说,这是一个很好的观点。我并不是反对这一点。我想传达的是,如果我们开始使用“;”,从长远来看,对大多数人来说会更容易。我是说“;”比“&”更适合所有人使用。我还想说的是,在所有人都切换到一个或另一个之前,我们将不得不与一个以不同的方式处理的团队打交道,所以如果我们想要健壮的代码,无论如何,我们都需要能够同时处理两者。
4赞 Shawn Kovac 1/26/2016 #3

简而言之,HTML 是一团糟(由于它的宽松),使用分号有助于简化这一点。我估计,当我考虑到我发现的复杂性时,使用与号作为分隔符会使整个过程复杂到使用分号作为分隔符的三倍!

我是一名 .NET 程序员,据我所知,.NET 本身不允许使用“;”分隔符,所以我编写了自己的解析和处理方法,因为我看到了使用分号的巨大价值,而不是使用与号作为分隔符的已经有问题的系统。不幸的是,非常受人尊敬的人(如另一个答案中的@Bob Aman)没有看到为什么分号的使用比使用与号要优越得多,而且简单得多的价值。因此,我现在分享几点,以说服其他尚未认识到使用分号的价值的受人尊敬的开发人员:

在 HTML 页面中使用像 '?a=1&b=2' 这样的查询字符串是不正确的(没有先对其进行 HTML 编码),但大多数时候它都可以工作。然而,这只是由于大多数浏览器是宽容的,并且这种宽容可能会导致难以发现的错误,例如,键值对的值在没有正确编码的情况下发布在 HTML 页面 URL 中(在 HTML 源代码中直接作为“?a=1&b=2”)。像 '?who=me+&+you' 这样的 QueryString 也有问题。

我们这些人可能会有偏见,并且可能会整天不同意我们的偏见,因此认识到我们的偏见非常重要。例如,我同意我只是认为用“;”分隔看起来“更干净”。我同意我的“更干净”的观点纯粹是一种偏见。而另一个开发人员可能具有同样相反但同样有效的偏见。因此,我对这一点的偏见并不比相反的偏见更正确。

但是,鉴于分号的公正支持,从长远来看,每个人的生活都更轻松,当考虑到整个画面时,这是无可争议的。简而言之,使用分号确实让每个人的生活更简单,但有一个例外:习惯新事物的一个小障碍。就这样。做出任何改变总是更加困难。但是,与继续使用&的持续困难相比,进行更改的难度相形见绌。

用;作为 QueryString 分隔符使它变得简单得多。与号分隔符正确编码的难度是使用分号的两倍多。(我认为)大多数实现都没有正确编码,因此大多数实现的复杂程度不会增加一倍。但是,跟踪和修复错误会导致生产力下降。在这里,我指出了当 & 为分隔符时正确编码 QueryString 所需的 2 个单独的编码步骤:

  • 第 1 步:对查询字符串的键和值进行 URL 编码。
  • 第 2 步:在对第 1 步进行 URL 编码后,将键和值(如“a=1&b=2”)连接起来。
  • 步骤3:然后HTML在页面的HTML源代码中对整个QueryString进行编码。

因此,为了正确(无错误)的 URL 编码,必须进行两次特殊编码,不仅如此,编码是两种截然不同的不同编码类型。第一个是 URL 编码,第二个是 HTML 编码(用于 HTML 源代码)。如果其中任何一个不正确,那么我可以为你找到一个错误。但是,对于 XML,步骤 3 是不同的。对于 XML,则需要 XML 字符实体编码(几乎相同)。我的观点是,最后的编码取决于 URL 的上下文,无论是在 HTML 网页中,还是在 XML 文档中。

现在有了更简单的分号分隔符,这个过程就像人们所期望的那样:

  • 1:URL对键和值进行编码,
  • 2:将值连接在一起。(步骤 3 没有编码。

我认为大多数 Web 开发人员会跳过第 3 步,因为浏览器非常宽松。但是,这会导致错误和更多复杂情况,当寻找这些错误时,或者如果这些错误不存在,用户将无法做事,或者编写错误报告等。

实际使用中的另一个复杂情况是使用 C# 和 VB.NET 在源代码中编写 XML 文档标记时。由于 & 必须编码,从字面上看,这确实拖累了我的生产力。额外的步骤 3 也使阅读源代码变得更加困难。因此,这种难以阅读的缺陷不仅适用于 HTML 和 XML,也适用于 C# 和 VB.NET 代码等其他应用程序,因为它们的文档使用 XML 文档。因此,步骤 #3 编码复杂性也扩散到其他应用程序。

所以总而言之,使用 ;因为分隔符很简单,因为使用分号时的(正确)过程是 WUD 通常期望的过程:只需要进行一个编码步骤。

也许这并不太令人困惑。但是所有的混淆或困难都是由于使用了 HTML 编码的分隔字符。因此,“&”是罪魁祸首。分号缓解了所有这些复杂性。

(我要指出的是,我上面的 3 步与 2 步过程通常是大多数应用程序需要多少步骤。但是,对于完全健壮的代码,无论使用哪种分隔符,都需要所有 3 个步骤。但根据我的经验,大多数实现都是草率且不健壮的。因此,使用分号作为查询字符串分隔符将使更多人的生活更轻松,网站和互操作错误更少,如果每个人都采用分号作为默认分号而不是与号。

评论

1赞 Bob Aman 2/3/2016
因此,在某种程度上,W3C 的手被束缚了,因为继承了 SGML 实体引用语法,而且 URL 语法在其他地方也同样已经定义了。但是,在规范之外重新定义规范的行为是有效互操作的最糟糕做法。假设我是一个规范实现者。我通读了规范,并精确而完美地实现了它。理想情况下,我应该能够与同样做过同样事情的其他人进行互操作。但是,一旦我们中的一个人合并了额外的规则,就没有更多的互操作了。这就是为什么 W3C 是错误的。
0赞 Bob Aman 2/3/2016
此外,源代码注释中的 FWIW、XML 也非常愚蠢。不过,这个不在 W3C 上。
1赞 Shawn Kovac 2/5/2016
@BobAman您声称“一旦我们中的一个人合并了附加规则,就没有更多的互操作了”。但事实并非如此。这就像说,如果你的服务器使用 POP3,而我的服务器只使用 IMAP,那么就没有更多的互操作了,所以无论谁编写了 IMAP,都是错的。伙计,这叫做用更好的替代品来增加技术。IMAP 问题的解决方案与 ;URL 中的分隔符:注意两者,并使用服务器使用的分隔符。没有混淆。你让它变得比现在更难。旧技术被新标准淘汰了。这是其中之一。
0赞 Shawn Kovac 2/5/2016
所以鲍勃,我问你怎么会缺乏互操作性?无论 Web 服务器使用哪个字符,用户只能使用服务器本身使用的分隔符。之美 ;是与使用 & 号相比有几个优点:& 号需要额外的编码,这在现实中几乎从未完成过,我在回复中对此进行了解释。所以我甚至看不到一种方式;不如使用 & 符号,只是一些服务器在实现方面滞后于更新的更好选项。我从来没有感到惊讶的是,为什么这么多人仅仅因为它是新的而拒绝它。
1赞 Bob Aman 2/9/2016
您似乎对互操作的含义感到困惑。标准机构通常要求至少两个由不同方编写的可互操作的实现。如果客户端和服务器由同一个人编写,则不是互操作。“选择与服务器相同的分隔符”根本不是互操作。规范的重点在于,我应该确切地知道如何根据规范中给出的规则来解释一段数据。如果我需要知道您支持或不支持不同的分隔符,那就是“带外”,它不再是真正的互操作。
40赞 geira 11/23/2016 #4

1999 年的 W3C 建议书已经过时。根据 2014 年 W3C 建议,目前的状态是分号作为参数分隔符现在是非法的

要解码 application/x-www-form-urlencoded 有效负载,应使用以下算法。[...]此算法的输出是名称-值对的排序列表。[...]

  1. 设字符串是严格拆分 U+0026 AMPERSAND 字符 (&) 上的字符串有效负载的结果。

换句话说,意味着参数将具有值;而应该导致(尽管在技术上是非法的,因为第二个应该被转义到)。?foo=bar;bazfoobar;baz?foo=bar;baz=snafoobar;baz=sna=%3D

评论

10赞 Zectbumo 11/14/2017
这个答案具有误导性,因为它严格地谈论的是表单编码,这不是 OP 所问的,也不在包含的示例中。表单 url 编码非常古老,用于通过 <form> 标签发送数据,我们正在远离该标签,现在转向 AJAX。使用&作为分隔符是一个古老的不幸的“错误”,现在由于向后兼容性的原因而被保留。使用分号是前进的方向,前提是您的 Web 服务器支持它。
7赞 geira 11/16/2017
如果您阅读 HTTP 和 URL 标准,您会看到它们除了转义之外没有为查询字符串定义任何语法。事实上,提到的两个文档是现存查询参数的唯一规范。虽然从技术上讲,表单编码(W3C 建议书都描述了)与 POST 请求相关,但 GET 没有类似的规范,因此浏览器实现遵循前者。现代框架(例如Mojolicious)也放弃了对分号分隔符的支持,除非所有浏览器都被重写,否则与号永远不会消失。
2赞 geira 11/16/2017
至于向 AJAX 迈进,不要以为当前的 Swagger(又名 OpenAPI)标准只允许使用与号分隔的参数;分号仅允许用作路径或 cookie 参数。如果您设计的 API 与 Swagger 规范相矛盾,则存在问题。
1赞 Zectbumo 11/17/2017
当然,规范没有定义分隔符。由我们自己做出明智的决定来分隔我们的参数,这样我们就不必转义放置在 html 属性中的 URL 中常见的参数。我们也可以搬起石头砸自己的脚,在 HTML 属性中使用和逃避。我不怪 Swagger。毕竟,他们希望他们的服务能够在尽可能多的服务器上工作,因此他们选择了最弱的公分母。因此,如果您的 Web 服务器支持分号,并且您正在编写自己的 URL,那么请比其他服务器更聪明:使用分号。;&
0赞 Savitoj Cheema 2/12/2019
我陷入了浏览器兼容性问题,我的 s3 图像链接需要一个参数,它适用于 chrome/firefox 和最新的 safari 浏览器,但在 Microsoft edge 和 IE 11 上失败,关于我如何解决这个问题的任何建议X-Amz-SignedHeaders: content-type;host