简体   繁体   中英

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?

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" , ie 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, eg

  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 .

I think you shouldn't have used comma as delimiter of the array.

I would recommend to

  • send json data using POST (which requires API change)

or use another string as delimiter. For example, @@@ .

FYI, you can simply join your array into string like this.

array.join(',')

From $http docs

If you wish override the request/response transformations only for a single request then provide transformRequest and/or transformResponse properties on the configuration object passed into $http.

Note that if you provide these properties on the config object the default transformations will be overwritten. If you wish to augment the default transformations then you must include them in your local transformation array.

In short you can use your encodeURIComponent() functionality to replace the default one by including transformRequest property in the config object for each request or you can establish a global override

See "Transforming Requests and Responses" in $http docs for more details

Not sure why you want to send this as GET in the first place

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM