318

I'm looking into what is the correct way to pass multiple values for the same parameter name in a GET request.

I've seen URLs like this:

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

And I've seen URLs like this:

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

My understanding is that the first is correct, but I can't find any reference for this. I had a look at the http spec but couldn't see anything about how the 'query' part of a URL should be made up.

I don't want an answer that says "either is fine" - if I'm building a webservice, I want to know which of these methods is standard so that people using my webservice know how to pass multiple parameters for the same name.

So, can someone point me at an official reference source to confirm which option is correct?

stripybadger
  • 4,539
  • 3
  • 19
  • 26

7 Answers7

250

Indeed, there is no defined standard. To support that information, have a look at wikipedia, in the Query String chapter. There is the following comment:

While there is no definitive standard, most web frameworks allow multiple values to be associated with a single field.[3][4]

Furthermore, when you take a look at the RFC 3986, in section 3.4 Query, there is no definition for parameters with multiple values.

Most applications use the first option you have shown: http://server/action?id=a&id=b. To support that information, take a look at this Stackoverflow link, and this MSDN link regarding ASP.NET applications, which use the same standard for parameters with multiple values.

However, since 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.

Community
  • 1
  • 1
EduardoFernandes
  • 3,091
  • 1
  • 13
  • 12
  • In the absence of any information to the contrary, I guess you're right - if RFC3986 doesn't specify a standard then there isn't one. Thanks Eduardo. – stripybadger Jan 05 '16 at 14:43
  • 43
    A would suggest using `id=a&id=b` as boolean AND, and `id=a,b` as boolean OR. – Alex Skrypnyk May 07 '16 at 05:13
  • 22
    FWIW PHP doesn't support reading args like `?id=5&id=3`. PHP would only read in one value for id here. If I remember correctly, it would have to look like this for it to work with PHP: `?id[]=5&id[]=3` – What have you tried Oct 07 '16 at 16:26
  • 4
    +1 for `since 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 Jan 12 '18 at 00:37
  • 11
    `id=a,b` makes the assumption that coma `,` is a valid delimiter. But your parameter values could contain a `,`. Then the client needs to escape `,` in the query parameter values. But you could decide `;` is better. It means the client and server should share the official delimiter for your API. `id=a&id=b` does not have this problem even though it makes urls longer – Ronan Quillevere Jan 12 '18 at 16:04
  • indeed the choice is up to the implementer of the service as the host language grants capabilities that can make easier the work by employing one string format or another. For example: Why not send the as an url enconded json array www.domin.com/resource?ids=%5B1,2,3%5D (decoded is "[1,2,3]") and process it with a language-specific json parser library that makes the work simpler and better for you.. personally i prefer effective and robust – Victor May 11 '18 at 17:48
  • may be there is no standard way, for me it worked as suggested by @Whathaveyoutried , i.e. `?id[]=5&id[]=3` Thanks a Lot !!! – weima May 08 '19 at 17:17
  • @AlexSkrypnyk That seems intuitive at first, but what if you are actually using query params to denote *unique* identifiers? A query string denoting `id=1&id=2` doesn't make sense; there will be no record that has an id equal to both 1 and 2. – BrDaHa Sep 28 '21 at 23:47
  • FWIW, both Rails (ruby) and Sinatra (ruby) use the `&foo[]=1&foo[]=2&...` style. – Michael Campbell Aug 10 '23 at 19:11
20

I would suggest looking at how browsers handle forms by default. For example take a look at the form element <select multiple> and how it handles multiple values from this example at 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>

For PHP use:

<select name="cars[]" multiple>

Live example from above at w3schools.com

From above if you click "saab, opel" and click submit, it will generate a result of cars=saab&cars=opel. Then depending on the back-end server, the parameter cars should come across as an array that you can further process.

Hope this helps anyone looking for a more 'standard' way of handling this issue.

phanf
  • 661
  • 1
  • 11
  • 16
13

I am describing a simple method which worked very smoothly in Python (Django Framework).

1. While sending the request, send the request like this

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

2. Now in my backend, I split the value received with a split function which always creates a list.

id_filter = id.split(',')

Example: So if I send two values in the request,

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

then the filter on the data is

id_filter = ['a', 'b']

If I send only one value in the request,

http://server/action?id=a

then the filter outcome is

id_filter = ['a']

3. To actually filter the data, I simply use the 'in' function

queryset = queryset.filter(model_id__in=id_filter)

which roughly speaking performs the SQL equivalent of

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

with the first request and,

WHERE model_id IN ('a')

with the second request.

This would work with more than 2 parameter values in the request as well !

MGLondon
  • 1,557
  • 15
  • 18
  • 1
    What if the value itself has a comma? Like I may have 2 values like: "abc" "p,q" – Vipul Agarwal May 19 '21 at 18:25
  • 1
    @VipulAgarwal I would either, a) Escape the comma. b) Use the ASCI encoding for a comma. c) Use a different character, `;|¦¬`, etc. d) State that a comma cannot be used for that query parameter in the API documentation.... There really are *a lot* of ways to deal with this, and it's no different to stating that you want to use an ampersand (`&`) in the query parameter. All the same workarounds will apply to using a comma. – Jack_Hu Oct 02 '21 at 13:39
4

My answer is more PHP-oriented.

Submitting multi-value form fields, i.e. submitting arrays, can be done in several different ways, as a standard is not necessarily spelled out.

Three possible ways to send multi-value fields or arrays would be:

  • ?cars[]=Saab&cars[]=Audi (Best way- PHP reads this into an array)
  • ?cars=Saab&cars=Audi (Bad way- PHP will only register last value)
  • ?cars=Saab,Audi (General way- You need to explode string to get values as array)

For Example :

http://localhost:3000/foo?id[]=a&id[]=b

Returns

Array
(
  [id] => Array
     (
       [0] => a
       [1] => b
     )
)

(NOTE: In this case, it would be important to name query key to some_name[], so that the resulting request vars would be registered as an array by PHP)

Shakil Alam
  • 308
  • 4
  • 9
3

Solutions above didn't work. It simply displayed the last key/value pairs, but this did:

http://localhost/?key[]=1&key[]=2

Returns:

Array
(
[key] => Array
    (
        [0] => 1
        [1] => 2
    )
Robert Sinclair
  • 4,550
  • 2
  • 44
  • 46
2

there is no standard, but most frameworks support both, you can see for example for java spring that it accepts both here

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

And Spring MVC will map a comma-delimited id parameter:

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

Or a list of separate id parameters:

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

Since the url is single parameter and multiple values. A very simple solution in Java is to split the string and then append it to self. For example below:

String baseUrl = "http://server/action"
String id = "a,b";
StringBuilder url = new StringBuilder();
url = baseUrl.append("?");
String[] idArr = id.split(",");
StringBuilder sb = new StringBuilder();
for ( String fetchId : idArr) {
        sb.append("&id=").append(fetchId);
        url.append(sb);
}
Laurel
  • 5,965
  • 14
  • 31
  • 57
vicky
  • 29
  • 1
  • 3
  • 9