Is it possible to specify the order of parameters using the Angular $ http service?

In my Angular app, I have a service that it uses $http

to fetch data from the server. The server endpoint uses HMAC authentication and expects the query string parameters to be in a specific order in the URL.

Angular sorts the parameters $http

when building the URL
, so it is not possible to specify the order of the custom parameters.

Here's an example:

this.apiCall = function() {
    return $http({
        method: 'GET',
        url: 'http://example.com/url/v1/endpoint',
        params: {
            'c': 'cdata',
            'a': 'adata',
            'b': 'bdata'
        }
    });
};

      

Angular build a URL like http://example.com/url/v1/endpoint?a=adata&b=bdata&c=cdata

, but I need to keep the order of the parameters as indicated http://example.com/url/v1/endpoint?c=cdata&a=adata&b=bdata

.

I understand that I can just bind the parameters to the URL string manually, but this is not very convenient and does not make it easy to manage interceptors $http

.

Angular probably sorts the parameters to maintain uniform behavior across browser implementations, since object ordering is not specified in ECMAScript.

Regardless , does anyone know how to get around Angular's default parameter sorting behavior in order to create a URL that stores the parameters specified?

+3


source to share


2 answers


I improved your solution by making something more streaming and guaranteed to work:

$httpProvider.interceptors.push(function() {
    return {
        request: function (config) {
            if (!config.paramOrder) {
                return config;
            }

            // avoid leaking config modifications
            config = angular.copy(config, {});

            var orderedParams = [];
            config.paramOrder.forEach(function (key) {
                if (config.params.hasOwnProperty(key)) {
                    orderedParams.push(encodeURIComponent(key) + '=' + encodeURIComponent(config.params[key]));
                    // leave only the unordered params in the `params` config
                    delete config.params[key];
                }
            });

            config.url += (config.url.indexOf('?') === -1) ? '?' : '&';
            config.url += orderedParams.join('&');

            return config;
        },
    };
});

      

Call the following:



$http({
    method: 'GET',
    url: 'http://example.com/url/v1/endpoint',
    params: {
        a: 'aValue',
        b: 'bValue',
        c: 'cValue'
    },
    paramOrder: ['c', 'a']
});

      

to get the query string starting with the key c

and then a

. Parameters not mentioned in paramOrder

will be added after the ordered parameters (in alphabetical order).

+3


source


I ended up creating a rudimentary interceptor to save the "as specified" order of parameters. This interceptor is triggered if a $http

configuration variable is set for the call keepParamsOrder

.

In your module config:

$httpProvider.interceptors.push(function() {
    return {
        'request': function(config) {
            if (!config.keepParamsOrder || !config.params) {
                return config;
            }

            var queryStrings = [];
            for (var key in config.params) {
                if (config.params.hasOwnProperty(key)) {
                    queryStrings.push(key + '=' + config.params[key]);
                }
            }

            // Reset the params to be empty
            config.params = {};

            config.url += (config.url.indexOf('?') === -1) ? '?' : '&';
            config.url += queryStrings.join('&');

            return config;
        },
    };
});

      



Tell it to run in the service invocation config:

this.apiCall = function() {
    return $http({
        method: 'GET',
        url: 'http://example.com/url/v1/endpoint',
        params: {
            'c': 'cdata',
            'a': 'adata',
            'b': 'bdata'
        },
        keepParamsOrder: true
    });
};

      

+1


source







All Articles