Bonne façon de transmettre plusieurs valeurs pour le même nom de paramètre dans la demande GET

211

Je cherche quelle est la bonne façon de transmettre plusieurs valeurs pour le même nom de paramètre dans une demande GET.

J'ai vu des URL comme celle-ci:

http://server/action?id=a&id=b

Et j'ai vu des URL comme celle-ci:

http://server/action?id=a,b

Je crois comprendre que le premier est correct, mais je ne trouve aucune référence à ce sujet. J'ai jeté un œil à la spécification http mais je n'ai rien vu sur la manière dont la partie «requête» d'une URL devrait être constituée.

Je ne veux pas de réponse qui dit "non plus c'est bien" - si je construis un webservice, je veux savoir laquelle de ces méthodes est standard afin que les personnes utilisant mon webservice sachent comment passer plusieurs paramètres pour le même nom.

Alors, quelqu'un peut-il me diriger vers une source de référence officielle pour confirmer quelle option est correcte?

stripybadger
la source

Réponses:

175

En effet, il n'y a pas de norme définie. Pour prendre en charge ces informations, consultez wikipedia, dans le chapitre Chaîne de requête . Il y a le commentaire suivant:

Bien qu'il n'y ait pas de norme définitive, la plupart des frameworks Web permettent d'associer plusieurs valeurs à un seul champ. [3] [4]

De plus, lorsque vous jetez un œil à la RFC 3986 , dans la section 3.4 Requête , il n'y a pas de définition pour les paramètres avec plusieurs valeurs.

La plupart des applications utilisent la première option que vous avez montré: http://server/action?id=a&id=b. Pour prendre en charge ces informations, consultez ce lien Stackoverflow et ce lien MSDN concernant les applications ASP.NET, qui utilisent la même norme pour les paramètres avec plusieurs valeurs.

Cependant, puisque vous développez les API, je vous suggère de faire ce qui est le plus simple pour vous, car l'appelant de l'API n'aura pas beaucoup de mal à créer la chaîne de requête.

EduardoFernandes
la source
En l'absence d'informations contraires, je suppose que vous avez raison - si la RFC3986 ne spécifie pas de norme, il n'y en a pas. Merci Eduardo.
stripybadger
22
A suggérerait d'utiliser id=a&id=bcomme booléen AND et id=a,bcomme boolean OR.
Alex Skrypnyk
17
FWIW PHP ne prend pas en charge la lecture d'arguments comme ?id=5&id=3. PHP ne lirait qu'une seule valeur pour id ici. Si je me souviens bien, cela devrait ressembler à ceci pour que cela fonctionne avec PHP:?id[]=5&id[]=3
Qu'avez-vous essayé
3
+1 poursince you are developing the APIs, I suggest you to do what is the easiest for you, since the caller of the API will not have much trouble creating the query string.
Amr
2
id=a,bfait l'hypothèse que la virgule ,est un délimiteur valide. Mais vos valeurs de paramètre peuvent contenir un ,. Ensuite, le client doit s'échapper ,dans les valeurs des paramètres de requête. Mais vous pouvez décider que ;c'est mieux. Cela signifie que le client et le serveur doivent partager le délimiteur officiel de votre API. id=a&id=bn'a pas ce problème même si cela rallonge les URL
Ronan Quillevere
6

Je suggérerais de regarder comment les navigateurs gèrent les formulaires par défaut. Par exemple, jetez un œil à l'élément de formulaire <select multiple>et à la façon dont il gère plusieurs valeurs de cet exemple sur w3schools.

<form action="/action_page.php">
<select name="cars" multiple>
  <option value="volvo">Volvo</option>
  <option value="saab">Saab</option>
  <option value="opel">Opel</option>
  <option value="audi">Audi</option>
</select>
<input type="submit">
</form>

Pour une utilisation PHP:

<select name="cars[]" multiple>

Exemple en direct d'en haut sur w3schools.com

D'en haut, si vous cliquez sur "saab, opel" et cliquez sur Soumettre, il générera un résultat de cars = saab & cars = opel . Ensuite, en fonction du serveur principal, les wagons de paramètres doivent apparaître comme un tableau que vous pouvez traiter ultérieurement.

J'espère que cela aidera tous ceux qui recherchent une manière plus «standard» de gérer ce problème.

phanf
la source
3

Je décris une méthode simple qui fonctionnait très bien en Python (Django Framework).

1. Lors de l'envoi de la demande, envoyez la demande comme ceci

http://server/action?id=a,b

2. Maintenant dans mon backend, je divise la valeur reçue avec une fonction de division qui crée toujours une liste.

id_filter = id.split(',')

Exemple: Donc, si j'envoie deux valeurs dans la requête,

http://server/action?id=a,b

alors le filtre sur les données est

id_filter = ['a', 'b']

Si j'envoie une seule valeur dans la demande,

http://server/action?id=a

alors le résultat du filtre est

id_filter = ['a']

3. Pour filtrer réellement les données, j'utilise simplement la fonction «in»

queryset = queryset.filter(model_id__in=id_filter)

qui, en gros, exécute l'équivalent SQL de

WHERE model_id IN ('a', 'b')

avec la première demande et,

WHERE model_id IN ('a')

avec la deuxième demande.

Cela fonctionnerait également avec plus de 2 valeurs de paramètres dans la demande!

MGLondon
la source
0

il n'y a pas de standard, mais la plupart des frameworks supportent les deux, vous pouvez voir par exemple pour java spring qu'il accepte les deux ici

@GetMapping("/api/foos")
@ResponseBody
public String getFoos(@RequestParam List<String> id) {
    return "IDs are " + id;
}

Et Spring MVC mappera un paramètre d'ID délimité par des virgules:

http://localhost:8080/api/foos?id=1,2,3
----
IDs are [1,2,3]

Ou une liste de paramètres d'id séparés:

http://localhost:8080/api/foos?id=1&id=2
----
IDs are [1,2]
Ousama Hadj Aissa
la source
Veuillez ne pas publier uniquement des URL simples. Ils peuvent devenir invalides à l'avenir.
mate00