1

I'm setting a couple of default headers using $http.defaults.headers.common for communication with our API – e.g. the Authorization header. This saves me a lot of trouble of specifying these headers on every individual $http request or $resource declaration.

However, in one place I'm making an $http.get call to the Foursquare API and the fact that the additional headers exist is a problem a) obviously I don't want to send the authorization header to anything other than our API and b) the existence of the headers forces $http to use CORS and Foursquare rejects the OPTIONS request.

Is there any way I can set the defaults on a per-host basis or using some other context? I've tried moving the directive that contacts Foursquare into its own module hoping the defaults might be isolated that way but they're not.

I guess I can delete the additional headers from $http.defaults prior to the Foursquare request and restore them afterwards but it feels like a horrible hack and might be problematic if any requests to our API are attempted while waiting for the Foursquare response to come back.

1
  • 1
    Also worth noting that I found that while I can explicitly turn off the headers by passing {headers:{Authorization:null}} to the $http.get the request still gets pre-flighted so that doesn't work. Commented Nov 15, 2013 at 15:24

2 Answers 2

1

What you may consider doing is creating a service as an abstraction layer. In that service you can compare the url with a list of trusted endpoints (your api) and only add the header if the url matches.

(function () {
'use strict';

var serviceId = 'webRequest';
angular.module('app').factory(serviceId, ['common', 'config', '$http', '$cookies', webRequest]);

function webRequest(common, config, $http, $cookies) {
    var $q = common.$q;

    var service = {
        WebRequest: WebRequest
    };
    return service;

    function WebRequest(method, url, data, okCallback, koCallback) {
        //inspect url here and if it matches config.trustedEndpoint or something similar          then...
        var promise = $http({
            method: method,
            url: url,
            data: data,
            headers: { 'Authorization': $cookies.AuthCookie}
        }).success(okCallback).error(koCallback);
        //otherwise, make the call without the header.
        return promise;
    }
}
})();

Additional approach would be to extend ng-Resource and override the default implementation for get.

Another approach may be to extend ng-Resource and override the default implementations.

var module = angular.module('customResource', ['ngResource']);

module.factory( 'Resource', [ '$resource', function( $resource ) {
    return function( url, params, methods ) {
      var defaults = {
      get: { method: 'get' }
      };

    methods = angular.extend( defaults, methods );

    var resource = $resource( url, params, methods );

    resource.prototype.$get = function() {
        //inspect url of this here and add header if needed

    };

    return resource;
};
}]);
Sign up to request clarification or add additional context in comments.

3 Comments

I think that would be a great idea if I wasn't using $resource almost everywhere so the actual $http call is a layer of abstraction below what I'm dealing with. In the case of the Foursquare request I'm using $http directly but it's with the $resource usage that using $http.defaults.headers really shines.
Another approach in this scenario may be to extend ng-Resource and override the default implementations. I can provide a sample if you'd like.
I added an example for extending ng-Resource to the answer.
0

I found a good way to solve this without having to use $http.defaults.

Instead I register an interceptor as described in the Angular docs. Within that I can modify the request config as I please:

request: (config) ->
  if config.url.indexOf('http://myhost.com') is 0
    if $cookies.AuthToken? and not config.headers['Authorization']?
      config.headers['Authorization'] = "Token #{$cookies.AuthToken}" 
  config

```

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.