Posição autorizada de chaves de consulta HTTP GET duplicadas

137

Estou com problemas para encontrar informações autorizadas sobre o comportamento dos campos duplicados da sequência de consultas HTTP GET, como

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

e, em particular, se o pedido for mantido ou não. A maioria das linguagens orientadas à web produz uma matriz que contém foo e bar associados a um "campo" principal, mas eu gostaria de saber se existe uma declaração autorizada (por exemplo, em uma RFC) sobre esse ponto. O RFC 3986 possui uma seção 3.4. Query, que se refere aos pares chave = valor, mas nada é dito sobre como interpretar a ordem e os campos duplicados e assim por diante. Isso faz sentido, já que é dependente de back-end e não está no escopo dessa RFC ...

Embora exista um padrão de fato, eu gostaria de ver uma fonte autorizada para isso, apenas por curiosidade.

Stefano Borini
fonte
Também estive pensando sobre isso. A outra coisa é a especificação sobre a mesclagem dos parâmetros da string de consulta com os do corpo do POST.
Thilo
No rancho de código, as pessoas dizem que não há garantia de pedidos. Mas esse segmento é antigo e ninguém apoia-lo de qualquer maneira: coderanch.com/t/357197/Servlets/java/getParameterValues-order
Thilo
1
Além do servidor manter a ordem da sequência de consultas, também há a pergunta sobre o navegador enviá-las na ordem DOM (ou em alguma outra ordem fixa).
Thilo

Respostas:

112

Não há especificações sobre isso. Você pode fazer o que quiser.

As abordagens típicas incluem: primeiro, último, conjunto de todos, junção de cadeia com vírgula de todos.

Suponha que a solicitação bruta seja:

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

Existem várias opções para o que request.query['tag']deve render, dependendo do idioma ou da estrutura:

request.query['tag'] => 'ruby'
request.query['tag'] => 'rails'
request.query['tag'] => ['ruby', 'rails']
request.query['tag'] => 'ruby,rails'
yfeldblum
fonte
12
Mais ao ponto da questão, há também a opção de ['rails', 'ruby'] (ordem diferente).
Thilo
2
Pode-se certamente fazer um grande número de coisas.
yfeldblum 18/11/2009
7
O .NET fornecerá você como uma matriz (não me importei com o pedido quando testei isso), o PHP fornecerá sempre o último e o Java (pelo menos o sistema com o qual trabalhei baseado em Java) sempre será o primeiro valor. stackoverflow.com/questions/1809494/…
SimonSimCity 8/12/12
17
Isso se baseia em um ataque chamado HTTP Parameter Pollution e foi analisado pelo OWASP: owasp.org/images/b/ba/AppsecEU09_CarettoniDiPaola_v0.8.pdf Na página 9, você encontrará uma lista de 20 sistemas e uma descrição de como eles lidam esse assunto.
precisa saber é o seguinte
1
@SimonSimCity além disso, o PHP criará uma matriz se você adicionar colchetes com um índice opcional ao nome do parâmetro.
Martin Ender
14

Posso confirmar que, para PHP (pelo menos na versão 4.4.4 e mais recente), funciona assim:

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

resulta em:

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

Mas

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

resulta em:

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

Esse comportamento é o mesmo para dados GET e POST.

SimonSimCity
fonte
1
O []sufixo parece um comportamento realmente estranho, mas se você tentar enviar uma matriz como argumento via jQuery .ajax(), ela será automaticamente adicionada da mesma maneira. Parece que isso é para benefício dos usuários de PHP.
Ian Clark
4
@IanClark É intuitivo para codificadores PHP - em PHP simples, $foo[] = 1anexa a uma matriz. O Django (Python) também faz a mesma coisa.
Izkata
Pode verificar no Apache Tomcat se retorna sequências concatenadas por vírgula.
Gaurav Ojha
8

A resposta de yfeldblum é perfeita.

Apenas uma observação sobre um quinto comportamento que notei recentemente: no Windows Phone , abrir um aplicativo com uma interface de usuário com uma chave de consulta duplicada resultará em NavigationFailed with:

System.ArgumentException: um item com a mesma chave já havia sido adicionado.

O culpado é System.Windows.Navigation.UriParsingHelper.InternalUriParseQueryStringToDictionary(Uri uri, Boolean decodeResults).

Portanto, o sistema nem permitirá que você lide com isso da maneira que quiser, o proibirá. Você tem a única solução para escolher seu próprio formato (CSV, JSON, XML, ...) e uri-escape-it.

Cœur
fonte
2
Isso parece um bug interno dessa função, em vez de uma escolha de design. A função provavelmente não verifica se há chaves duplicadas no dicionário que está criando. Os dicionários, é claro, exigem chaves exclusivas.
gligoran
1
Portanto, o navegador do cliente - não o servidor - está lançando um erro nesta situação? Parece um bug. Gostaria de saber se esse bug ainda existe hoje?
Jon Schneider
1
@ JonSchneider Sim, o cliente está lançando NavigationFailedpara esse URI. Mas, desculpe-me, abandonei o desenvolvimento do Windows (Phone) um mês após esta postagem e mudei para o macOS (iOS), então não posso mais ajudar a rastrear esse problema hoje em dia.
21418 Cœur
5

A maioria (todas?) Das estruturas não oferece garantias, portanto, assuma que elas serão retornadas em ordem aleatória.

Sempre adote a abordagem mais segura.

Por exemplo, interface Java HttpServlet: ServletRequest.html # getParameterValues

Até o método getParameterMap não menciona a ordem dos parâmetros (a ordem de um iterador java.util.Map também não pode ser invocada.)

Photodeus
fonte
3

Normalmente, valores de parâmetros duplicados, como

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

resultam em um único parâmetro queryString que é uma matriz:

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

Eu já vi esse comportamento no ASP, ASP.NET e PHP4.

3Dave
fonte
exatamente, esse é o padrão de fato, mas, tanto quanto vejo, não há uma decisão autorizada sobre ele. Como não acredito que seja esse o caso, sou incapaz de encontrá-lo.
Stefano Borini
2
Sim, provavelmente todo mundo já viu esse comportamento. A questão era se isso é realmente especificado em algum lugar.
Thilo
-1

Eu tive a mesma pergunta. Estou escrevendo a função javascript para analisar e modificar consultas. Não sei se uma string de consulta possui nomes duplicados ou entre colchetes, como x [] = 1 & x [] = 2, é padrão, embora alguns idiomas suportem esse formato.

Mas acho que o Chrome e o Firefox têm uma nova classe denominada URLSeachParamse suporta apenas o formato mais simples como name=value. Se houver nomes duplicados na string de consulta, o getmétodo deURLSearchParams retornará apenas o primeiro.

Então, pessoalmente, talvez um URL mais simples e sem nomes duplicados seja muito mais seguro para o futuro.

LCB
fonte
1
Se houver nomes duplicados na string de consulta, o método get de URLSearchParams retornará apenas o primeiro. Isso não está correto: você pode recuperar todo o valor como uma matriz usandoURLSearchParams.getAll('x')
Blaise
@ Blaise Muito obrigado, eu não entendi o recurso antes.
LCB