Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to properly send URL parameters containing commas using AngularJS?

I have a feeling I am just looking at this wrong, but I want to get feedback on the proper way to pass URL query parameters through Angular's $http.get() method - specifically, parameters that contain commas.

Let's say I have the following data, to be used as URL parameters in a GET request:

var params = {
  filter : [
     "My filter",
     "My other filter",
     "A filter, that contains, some commas"
  ],
  sort : [
     "ascending"
  ]
};

Now, I convert this structure to some parameters that can be fed into $http.get:

var urlParams = {};
angular.forEach(params, function(value, name) {
    urlParams[name] = "";
    for (var i = 0; i < value.length; i++) {
       urlParams[name] += value[i];
       if (i < value.length - 1) {
         urlParams[name] += ","
       }
    }
}

At this point, urlParams looks like this:

{
  filter : "My filter,My other filter,A filter, that contains, some commas",
  sort : "ascending"
}

Now, that isn't what I want, since the third filter parameter has now turned into three separate parameters. (The API I am working with does not allow multiple values for a parameter to be passed in any other way than: "?param=value1,value2,value3") So, what I need to do is URI encode these values first, right? So, I add a encodeURIComponent() to the above routine like this:

urlParams[name] += encodeURIComponent(value[i]);

This gives me a parameters object that looks like this:

{
  filter : "My%20filter,My%20other%20filter,A%20filter%2C%20that%20contains%2C%20some%20commas",
  sort : "ascending"
}

Now, I make a request:

var config = {
  params : urlParams
};
$http.get("/foo", config).then(function(response){
  console.log(response);
});

... and this doesn't work, since Angular encodes the URL parameters as well, so the request ends up looking like this:

GET "/foo?filter=My%2520filter,My%2520other%2520filter,A%2520filter%2C%20that%20contains%2C%20some%20commas&sort=ascending"

As you can see the parameters are being encoded twice (the % signs are being encoded as %25), which of course, won't work.

Obviously, I am doing it wrong. But what is the right way? Or, do I need to ask the API developer to accept URL parameters like this?

GET "/foo?filter=My+filter,+with+a+comma&filter=Another+filter"

where multiple parameter values are stated separately, instead of being comma delimited?

like image 488
Jeff Fohl Avatar asked Jan 22 '16 01:01

Jeff Fohl


1 Answers

As you've described the API, there is no way to reliably pass values containing commas.

Suppose you want to pass the items ["one","two","three,four"] as a list.

  • If you pass the strings as-is, the API will see (after the normal server-side URL decoding)

    one,two,three,four
    

    which makes the three,four indistinguishable from two separate items.

  • If you pass the strings URL-encoded, the entire parameter will be double-encoded, and the API will see (again, after URL decoding)

    one,two,three%2Cfour
    

    Now the parameters are distinguishable, but this requires support from the API to URL-decode each item separately.

  • Suppose you pass the strings like one,two,"three,four", i.e. items containing commas are quoted. The API can decode the parameters correctly, but it needs to support a more complex syntax (quoted strings) instead of simply splitting by commas...

...and so on. The bottom line is that without additional support from the API, I don't think there is anything you can do client-side to trick it into decoding strings containing commas correctly. There are many tweaks that the API developer can make, e.g.

  1. Accepting some escape sequence for commas within list items which is unescaped server-side.
  2. Accepting each item in a separate URL parameter.
  3. Accepting JSON-encoded body via POST.

You will need to ask the API developer to do something.

like image 200
Igor Raush Avatar answered Sep 23 '22 09:09

Igor Raush