Position faisant autorité des clés de requête HTTP GET en double

137

J'ai du mal à trouver des informations faisant autorité sur le comportement des champs en double de la chaîne de requête HTTP GET, comme

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

et notamment si la commande est conservée ou non. La plupart des langages orientés Web produisent un tableau contenant à la fois foo et bar associés à un "champ" clé, mais j'aimerais savoir si une déclaration faisant autorité existe (par exemple sur une RFC) à propos de ce point. La RFC 3986 a une section 3.4. Query, qui fait référence aux paires clé = valeur, mais rien n'est dit sur la façon d'interpréter l'ordre et de dupliquer les champs, etc. Cela a du sens, car il dépend du backend et n'est pas dans le cadre de cette RFC ...

Bien qu'une norme de facto existe, j'aimerais voir une source faisant autorité pour elle, juste par curiosité.

Stefano Borini
la source
Je me suis posé des questions à ce sujet aussi. L'autre chose est la spécification sur la fusion des paramètres de la chaîne de requête avec ceux du corps POST.
Thilo
Au ranch de code, les gens disent qu'il n'y a aucune garantie de commande. Mais ce fil est vieux et personne ne le sauvegarde de quelque manière que ce soit: coderanch.com/t/357197/Servlets/java/getParameterValues-order
Thilo
1
En plus du serveur gardant l'ordre de la chaîne de requête, il y a aussi la question du navigateur qui les envoie dans DOM (ou dans un autre ordre fixe).
Thilo

Réponses:

112

Il n'y a aucune spécification à ce sujet. Vous pouvez faire ce que vous aimez.

Les approches typiques incluent: première donnée, dernière donnée, tableau de tous, jointure de chaîne avec virgule de tout.

Supposons que la requête brute soit:

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

Ensuite, il existe différentes options pour ce qui request.query['tag']devrait rapporter, en fonction de la langue ou du cadre:

request.query['tag'] => 'ruby'
request.query['tag'] => 'rails'
request.query['tag'] => ['ruby', 'rails']
request.query['tag'] => 'ruby,rails'
Yfeldblum
la source
12
Plus au point de la question, il y a aussi l'option de ['rails', 'ruby'] (ordre différent).
Thilo
2
On peut certainement faire un grand nombre de choses.
yfeldblum
7
.NET vous donnera sous forme de tableau (je ne me suis pas soucié de l'ordre lorsque j'ai testé cela), PHP vous donnera toujours le dernier et Java (du moins le système avec lequel j'ai travaillé basé sur Java) toujours la première valeur. stackoverflow.com/questions/1809494/…
SimonSimCity
17
Ceci est basé sur une attaque appelée HTTP Parameter Pollution et a été analysé par OWASP: owasp.org/images/b/ba/AppsecEU09_CarettoniDiPaola_v0.8.pdf À la page 9, vous trouverez une liste de 20 systèmes et une description de leur gestion. ce problème.
SimonSimCity
1
@SimonSimCity en plus de cela, PHP créera en fait un tableau si vous ajoutez des crochets avec un index facultatif au nom du paramètre.
Martin Ender
14

Je peux confirmer que pour PHP (au moins dans la version 4.4.4 et plus récente) cela fonctionne comme ceci:

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

résulte en:

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

Mais

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

résulte en:

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

Ce comportement est le même pour les données GET et POST.

SimonSimCity
la source
1
Le []suffixe semble être un comportement vraiment étrange, mais si vous essayez d'envoyer un tableau en tant qu'argument via jQuery .ajax(), il les ajoutera automatiquement pour vous de la même manière. Il semble que cela profite aux utilisateurs PHP.
Ian Clark
4
@IanClark C'est intuitif pour les codeurs PHP - en PHP simple, $foo[] = 1ajoute à un tableau. Django (Python) fait également la même chose.
Izkata
Peut vérifier sur Apache Tomcat qu'il renvoie des chaînes concaténées par des virgules.
Gaurav Ojha
8

La réponse de yfeldblum est parfaite.

Juste une note sur un cinquième comportement que j'ai remarqué récemment: sur Windows Phone , l'ouverture d'une application avec un uri avec une clé de requête en double entraînera NavigationFailed with:

System.ArgumentException: un élément avec la même clé avait déjà été ajouté.

Le coupable est System.Windows.Navigation.UriParsingHelper.InternalUriParseQueryStringToDictionary(Uri uri, Boolean decodeResults).

Ainsi, le système ne vous laissera même pas le gérer comme vous le souhaitez, il l'interdira. Il ne vous reste plus qu'à choisir votre propre format (CSV, JSON, XML, ...) et uri-escape-it.

Cœur
la source
2
Cela semble être un bug interne de cette fonction, plutôt qu'un choix de conception. La fonction Probablement ne vérifie pas les clés en double dans le dictionnaire qu'elle crée. Les dictionnaires, bien sûr, nécessitent des clés uniques.
gligoran
1
Donc, le navigateur client - pas le serveur - génère une erreur dans cette situation? Cela ressemble à un bug. Je me demande si ce bug existe encore aujourd'hui?
Jon Schneider
1
@JonSchneider Oui, le client lance NavigationFailedun tel URI. Mais, pardonnez-moi, j'ai abandonné le développement de Windows (Phone) un mois après cet article et je suis passé à macOS (iOS), donc je ne peux plus m'empêcher de suivre ce problème de nos jours.
Cœur
5

La plupart (tous?) Des frameworks n'offrent aucune garantie, alors supposons qu'ils seront retournés dans un ordre aléatoire.

Adoptez toujours l'approche la plus sûre.

Par exemple, interface java HttpServlet: ServletRequest.html # getParameterValues

Même la méthode getParameterMap laisse de côté toute mention sur l'ordre des paramètres (l'ordre d'un itérateur java.util.Map ne peut pas non plus être invoqué.)

Photodeus
la source
3

En règle générale, dupliquez les valeurs de paramètres comme

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

résultent en un seul paramètre queryString qui est un tableau:

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

J'ai vu ce comportement dans ASP, ASP.NET et PHP4.

3Dave
la source
exactement, c'est la norme de facto, mais pour autant que je sache, il n'y a pas de décision faisant autorité à ce sujet. Puisque je ne crois pas que ce soit le cas, je suis juste incapable de le trouver.
Stefano Borini
2
Oui, probablement tout le monde a vu ce comportement. La question était de savoir si cela est réellement spécifié quelque part.
Thilo
-1

J'avais la même question. J'écris une fonction javascript pour analyser et stringifier les requêtes. Je ne sais pas si une chaîne de requête a des noms en double ou un nom avec des crochets, tels que x [] = 1 & x [] = 2, est standard bien que certaines langues prennent en charge ces formats.

Mais je trouve que Chrome et Firefox ont une nouvelle classe nommée URLSeachParamset qu'elle ne prend en charge que le format le plus simple name=value. S'il y a des noms en double dans la chaîne de requête, la getméthode de URLSearchParamsne renvoie que le premier.

Donc, personnellement, peut-être une URL de noms plus simple et sans doublons est beaucoup plus sûre pour l'avenir.

LCB
la source
1
S'il y a des noms en double dans la chaîne de requête, la méthode get de URLSearchParams ne renvoie que le premier. Ce n'est pas correct: vous pouvez récupérer toutes les valeurs sous forme de tableau en utilisantURLSearchParams.getAll('x')
Blaise
@Blaise Merci beaucoup, j'ai mal compris la fonctionnalité avant.
LCB