Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular does not encode the semi-colon character in an url

Tags:

angularjs

We need an encoded semi-colon character in our url parameter but angular does not encode this character.

The resource we use looks something like this:

app.factory('TestResource', ['$resource', function ($resource) {
    return $resource('http://somedomain.com');
}]);

app.run(['TestResource', function (TestResource) {
    TestResource.query({
        q: 'sin;sout'
    });
}]);

This is the result we get:

http://somedomain.com/?q=sin;sout

We want the url to be:

http://somedomain.com/?q=sin%3Bsout

But if we pre-encode the parameter before sending the % char get's encoded like this:

http://somedomain.com/?q=sin%253Bsout

How can we get the desired result? (http://somedomain.com/?q=sin%3Bsout)

like image 531
joente Avatar asked Sep 17 '25 00:09

joente


2 Answers

Angular uses its own function to encode the URL. And that function doesn't encode characters that usually don't need to be encoded like / or ?. ; is such a character, too. It's used in matrix URIs, e.g. So Angular's behavior actually conforms to the standard, but it could be a problem when such characters are used literally, i.e. without a special meaning. That seems to be the case here.

Since the URL is build just before sending the request, there's not much we can do. There is kind of a loophole though: Only parameters are encoded, not the base URL. So any workaround would involve creating the URL or at least a part of it yourself.

You could add an interceptor, that adds the properly encoded parameters to the URL before Angular does it. You could even completely replace Angular's behavior that way.

UPDATE:

Another solution came to my mind. The $http service delegates sending the actual request to the $httpBackend service which receives the already constructed URL. Using a decorator you can replace either the ; or the incorrectly encoded %253B with %3B right before the request is sent:

app.config(function($provide) {
  $provide.decorator('$httpBackend', function($delegate) {
    return function(method, url, post, callback, headers, timeout, withCredentials, responseType) {
      url = url.replace(';', '%3B');
      $delegate(method, url, post, callback, headers, timeout, withCredentials, responseType);
    };
  })
});
like image 164
a better oliver Avatar answered Sep 19 '25 21:09

a better oliver


Building on zeroflagL's answer one could consider changing the replace to change all occurrences of the semi-colon (as it is written it will only replace the first semi-colon):

url = url.replace(/;/g, '%3B');
like image 32
srobinet Avatar answered Sep 19 '25 19:09

srobinet