Авторитарная позиция дублирования ключей HTTP GET

У меня возникли проблемы с поиском авторитетной информации о поведении с повторяющимися полями строки запроса GET HTTP, например

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

и, в частности, если порядок сохранен или нет. Большинство веб-ориентированных языков создают массив, содержащий как foo, так и bar, связанные с ключевым полем, но я хотел бы знать, существует ли авторитетное утверждение (например, в RFC) об этой точке. RFC 3986 имеет раздел 3.4. Query, который ссылается на пары ключ = значение, но ничего не сказано о том, как интерпретировать порядок и дублировать поля и так далее на. Это имеет смысл, поскольку он зависит от бэкэнд, а не в рамках этого RFC...

Хотя существует де-факто стандарт, я бы хотел получить для него авторитетный источник, просто из любопытства.

Ответ 1

В этом нет никакой спецификации. Вы можете делать то, что вам нравится.

Типичные подходы включают в себя: 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'

Ответ 2

Я могу подтвердить, что для 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.

Ответ 3

Большинство (все?) фреймвордов не предлагают никаких гарантий, поэтому предположим, что они будут возвращены в случайном порядке.

Всегда применяйте безопасный подход.

Например, интерфейс java HttpServlet: ServletRequest.html#getParameterValues

Даже метод getParameterMap не содержит упоминания о порядке параметра (порядок итератора java.util.Map не может быть оговорен.)

Ответ 4

Ответ yfeldblum идеальный.

Просто примечание о пятом поведении, которое я заметил недавно: на Windows Phone, открытие приложения с помощью uri с дублирующимся ключом запроса приведет к тому, что NavigationFailed будет:

System.ArgumentException: элемент с тем же ключом уже добавлен.

Преступник System.Windows.Navigation.UriParsingHelper.InternalUriParseQueryStringToDictionary(Uri uri, Boolean decodeResults).

Таким образом, система даже не позволит вам обрабатывать ее так, как вы хотите, она запретит ее. Вы остаетесь единственным решением, чтобы выбрать свой собственный формат (CSV, JSON, XML,...) и uri-escape-it.

Ответ 5

Как правило, повторяющиеся значения параметров, такие как

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

приводит к одному параметру queryString, который представляет собой массив:

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

Я видел это поведение в ASP, ASP.NET и PHP4.

Ответ 6

У меня был тот же вопрос. Я пишу javascript функцию для синтаксического анализа и стробирования запросов. Я не знаю, имеет ли строка запроса двойные имена или имя с помощью скобок, например x [] = 1 & x [] = 2, хотя некоторые языки поддерживают этот формат.

Но я нахожу, что у Chrome и Firefox есть новый класс с именем URLSeachParams и он поддерживает только самый простой формат как name=value. Если в строке запроса есть повторяющиеся имена, метод get URLSearchParams возвращает только первый.

Так что лично, возможно, самый простой и не повторяющийся URL-адрес имен намного безопаснее для будущего.