重复HTTP GET查询键的权威位置

Ste*_*ini 134 uri http

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

http://example.com/page?field=foo&field=bar 
Run Code Online (Sandbox Code Playgroud)

特别是如果保留或不保留订单.大多数面向Web的语言产生一个包含与关键"字段"相关联的foo和bar的数组,但我想知道是否存在关于这一点的权威声明(例如在RFC上).RFC 3986有一个部分3.4. Query,它引用了键=值对,但没有说明如何解释顺序和重复字段等.这是有道理的,因为它依赖于后端,而不属于RFC的范围......

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

yfe*_*lum 107

没有规范.你可以做你喜欢的事.

典型的方法包括: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
Run Code Online (Sandbox Code Playgroud)

然后request.query['tag']根据语言或框架,有多种选择可以产生什么:

request.query['tag'] => 'ruby'
request.query['tag'] => 'rails'
request.query['tag'] => ['ruby', 'rails']
request.query['tag'] => 'ruby,rails'
Run Code Online (Sandbox Code Playgroud)

  • 这是基于一种名为HTTP参数污染的攻击,并已由OWASP分析:https://www.owasp.org/images/b/ba/AppsecEU09_CarettoniDiPaola_v0.8.pdf在第9页,您将找到20个系统的列表以及他们如何处理这个问题的描述. (17认同)
  • 更重要的是,还有['rails','ruby']选项(不同的顺序). (12认同)
  • .NET会给你一个数组(我在测试的时候并没有关心它的顺序),PHP会给你永远的最后一步而Java(至少我使用的系统基于Java)总是第一个值.http://stackoverflow.com/questions/1809494/post-the-checkboxes-that-are-unchecked/8972025#8972025 (6认同)
  • 人们当然可以做很多事情. (2认同)

小智 19

自从这个问题被提出并且接受的答案是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)。解析输出是“一个最初为空的名称-值元组列表,其中名称和值都包含一个字符串”,其中列表被定义为有限有序序列,并且键-值对按照它们的顺序添加到该列表中。出现在网址中。起初没有提到重复的键,但第 6.2 节 ( https://url.spec.whatwg.org/#interface-urlsearchparams ) 中的 URLSearchParams 类上的一些方法对排序设置了明确的期望:“getAll(name)方法步骤是按列表顺序返回名称为 name... 的所有名称-值对的值"; 该sort()方法指定“必须保留具有相同名称的名称-值对之间的相对顺序。 ”(强调我的)。检查添加排序方法的提交中引用的 Github 问题,我们发现最初的提议是对键相同的值进行排序,但这一点已更改:“默认排序不影响值顺序的原因是值的顺序可能很重要。我们不应该假设可以移动值的顺序。” (https://github.com/whatwg/url/issues/26#issuecomment-271600764


Sim*_*ity 14

我可以确认对于PHP(至少在4.4.4及更高版本中),它的工作原理如下:

GET /blog/posts?tag=ruby&tag=rails HTTP/1.1
Host: example.com
Run Code Online (Sandbox Code Playgroud)

结果是:

request.query['tag'] => 'rails'
Run Code Online (Sandbox Code Playgroud)

GET /blog/posts?tag[]=ruby&tag[]=rails HTTP/1.1
Host: example.com
Run Code Online (Sandbox Code Playgroud)

结果是:

request.query['tag'] => ['ruby', 'rails']
Run Code Online (Sandbox Code Playgroud)

对于GET和POST数据,此行为是相同的.

  • @IanClark PHP编码器直观 - 在普通的PHP中,`$ foo [] = 1`附加到数组.Django(Python)也做了同样的事情. (4认同)

Cœu*_*œur 7

yfeldblum的回答很完美.

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

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

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

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

  • 这似乎是该功能的内部错误,而不是设计选择.可能的函数不检查它正在创建的Dictionary中的重复键.当然,字典需要唯一的密钥. (2认同)

Pho*_*eus 5

大多数(所有?)框架都不提供任何保证,因此假设它们将以随机顺序返回.

始终采取最安全的方法.

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

甚至getParameterMap方法都没有提及有关参数顺序的任何提及(也不能依赖java.util.Map迭代器的顺序.)