【问题标题】:Authoritative position of duplicate HTTP GET query keys重复 HTTP GET 查询键的权威位置
【发布时间】:2010-12-17 07:39:54
【问题描述】:

我无法找到有关 HTTP GET 查询字符串重复字段的行为的权威信息,例如

http://example.com/page?field=foo&field=bar 

尤其是订单是否保留。大多数面向网络的语言都会生成一个数组,其中包含与关键“字段”关联的 foo 和 bar ,但我想知道关于这一点是否存在权威声明(例如在 RFC 上)。 RFC 3986 有一个部分 3.4. Query,它指的是 key=value 对,但没有说明如何解释 order 和重复字段等。这是有道理的,因为它依赖于后端,而不是在该 RFC 的范围内......

虽然存在事实上的标准,但出于好奇,我希望看到它的权威来源。

【问题讨论】:

  • 也一直在想这个。另一件事是关于将查询字符串中的参数与 POST 正文中的参数合并的规范。
  • 码农那边,人家说没有订单保证。但是该线程很旧,没有人以任何方式支持它:coderanch.com/t/357197/Servlets/java/getParameterValues-order
  • 除了服务器保持查询字符串的顺序外,还有浏览器以DOM(或其他固定)顺序发送它们的问题。

标签: http uri


【解决方案1】:

通常,重复参数值,如

http://example.com/page?field=foo&field=bar

产生一个作为数组的单个 queryString 参数:

field[0]=='foo'
field[1]=='bar'

我在 ASP、ASP.NET 和 PHP4 中看到过这种行为。

【讨论】:

  • 没错,这是事实上的标准,但据我所知,还没有权威的决定。由于我不相信是这样,我只是无能为力。
  • 是的,可能每个人都见过这种行为。问题是这是否真的在某处指定。
【解决方案2】:

大多数(全部?)框架不提供任何保证,因此假设它们将按随机顺序返回。

始终采取最安全的方法。

例如java HttpServlet接口: ServletRequest.html#getParameterValues

即使是 getParameterMap 方法也没有提及参数顺序(也不能依赖 java.util.Map 迭代器的顺序。)

【讨论】:

  • “不提供任何保证”或者可能是严重缺乏记录,并带有一些牛仔编码?
【解决方案3】:

没有规范。你可以为所欲为。

典型的方法包括:first-given、last-given、array-of-all、string-join-with-comma-of-all。

假设原始请求是:

GET /blog/posts?tag=ruby&tag=rails HTTP/1.1
Host: example.com

然后,request.query['tag'] 应该产生的结果有多种选择,具体取决于语言或框架:

request.query['tag'] => 'ruby'
request.query['tag'] => 'rails'
request.query['tag'] => ['ruby', 'rails']
request.query['tag'] => 'ruby,rails'

【讨论】:

  • 更切中要害,还有 ['rails', 'ruby'] 的选项(顺序不同)。
  • 一个人当然可以做很多事情。
  • .NET 会给你一个数组(我在测试时并不关心顺序),PHP 总是给你最后一个和 Java(至少我使用的基于 Java 的系统) ) 始终是第一个值。 stackoverflow.com/questions/1809494/…
  • 这是基于一种称为 HTTP 参数污染的攻击,并已由 OWASP 分析:owasp.org/images/b/ba/AppsecEU09_CarettoniDiPaola_v0.8.pdf 在第 9 页,您将找到 20 个系统的列表以及它们如何处理此问题的描述。
  • @SimonSimCity 除此之外,如果您将带有可选索引的方括号附加到参数名称,PHP 实际上会创建一个数组。
【解决方案4】:

我可以确认对于 PHP(至少在 4.4.4 和更高版本中)它的工作方式如下:

GET /blog/posts?tag=ruby&tag=rails HTTP/1.1
Host: example.com

结果:

request.query['tag'] => 'rails'

但是

GET /blog/posts?tag[]=ruby&tag[]=rails HTTP/1.1
Host: example.com

结果:

request.query['tag'] => ['ruby', 'rails']

GET 和 POST 数据的这种行为是相同的。

【讨论】:

  • [] 后缀看起来真的很奇怪,但是如果您尝试通过 jQuery 的.ajax() 发送一个数组作为参数,那么它会以同样的方式自动为您添加它们。看起来这是为了 PHP 用户的利益。
  • @IanClark 这对 PHP 编码人员来说很直观——在普通的 PHP 中,$foo[] = 1 附加到一个数组中。 Django (Python) 也做同样的事情。
  • 可以在 Apache Tomcat 上验证它返回逗号连接的字符串。
【解决方案5】:

yfeldblum 的回答很完美。

关于我最近注意到的第五个行为的注释:在 Windows Phone 上,使用带有重复查询键的 uri 打开应用程序将导致 NavigationFailed 并显示:

System.ArgumentException: 已添加具有相同键的项。

罪魁祸首是System.Windows.Navigation.UriParsingHelper.InternalUriParseQueryStringToDictionary(Uri uri, Boolean decodeResults)

所以系统甚至不会让你按照你想要的方式处理它,它会禁止它。您只有选择自己的格式(CSV、JSON、XML、...)和 uri-escape-it 的唯一解决方案。

【讨论】:

  • 这似乎是该功能的内部错误,而不是设计选择。可能的功能不会检查它正在创建的字典中的重复键。当然,字典需要唯一的键。
  • 所以 客户端浏览器——而不是服务器——在这种情况下会抛出错误?它看起来确实像一个错误。我想知道这个错误今天是否仍然存在?
  • @JonSchneider 是的,客户端正在为此类 URI 抛出 NavigationFailed。但是,请原谅我,在这篇文章发布一个月后,我放弃了 Windows(Phone)开发并转向了 macOS(iOS),所以现在我无法再帮助跟踪这个问题了。
【解决方案6】:

?array[]=value1&array[]=value2 方法无疑是一种非常流行的方法。

  • 大多数 Javascript 框架都支持
  • 受 Java Spring 支持
  • PHP 支持

【讨论】:

    【解决方案7】:

    自从提出这个问题并且接受的答案是 12 年前写的以来,情况似乎已经发生了变化。我相信我们现在有了一个权威来源:WHATWG URL 标准在第 6.2 节 (https://url.spec.whatwg.org/#interface-urlsearchparams) 和第 5.1 节关于 x-www-form-urlencoded 解析 (https://url.spec.whatwg.org/#urlencoded-parsing) 中详细描述了提取和解析查询字符串的过程.解析输出是“一个初始为空的名称-值元组列表,其中名称和值都包含一个字符串”,其中列表定义为有限有序序列,并添加键值对按照它们在 URL 中出现的顺序添加到此列表中。起初没有提到重复键,但是第 6.2 节中 URLSearchParams 类的一些方法(https://url.spec.whatwg.org/#interface-urlsearchparams)对排序设置了明确的期望:“getAll(name) 方法步骤是返回所有名称-值对的值,其名字就是名字...按列表顺序"; sort() 方法指定“必须保留具有相同名称的名称-值对之间的相对顺序。”(强调我的)。检查在添加排序方法的提交中引用的 Github 问题,我们看到最初的提议是对键相同的值进行排序,但这已更改:“默认排序不影响值顺序的原因是值的顺序可能很重要。我们不应该假设可以改变值的顺序。” (https://github.com/whatwg/url/issues/26#issuecomment-271600764)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-02
      • 1970-01-01
      • 1970-01-01
      • 2023-03-21
      • 2011-10-26
      相关资源
      最近更新 更多