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.


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'

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.


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.


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.)


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.


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.


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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.