Accessing $httpProvider configuration object

11,333 views
Skip to first unread message

David Brunner

unread,
Jan 25, 2012, 1:20:40 PM1/25/12
to ang...@googlegroups.com
Hello,

We're using AngularJS with Django.  Django has it's own approach to handling csrf tokens, so we need to add the token that Django expects to the default POST headers.  We can do this through the $httpProvider configuration object.

The only way I've been able to figure out to do this is to grab a reference to the configuration object in a module config function, and then modify the configuration object in a module run function which can depend on the $cookies service, as follows.

myApp.config(($httpProvider) -> myApp.$httpProvider = $httpProvider)

myApp.run(
   ['$cookies', ($cookies) -> myApp.$httpProvider.defaults.headers.post['X-CSRFToken'] = $cookies['csrftoken']]
)

Is there a better way?

Thanks,

David

Misko Hevery

unread,
Jan 25, 2012, 1:44:57 PM1/25/12
to ang...@googlegroups.com, Igor Minar, Vojta Jina
Hi Igor & Vojta,

this is a good point. It makes it hard to configure things, and there is a legitimate reason why you can't configure the XSRF until the app runs and gives you a token.

What do you guys think?

-- Misko

--
You received this message because you are subscribed to the Google Groups "AngularJS" group.
To view this discussion on the web visit https://groups.google.com/d/msg/angular/-/TG1bli_VoxEJ.
To post to this group, send email to ang...@googlegroups.com.
To unsubscribe from this group, send email to angular+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/angular?hl=en.

Igor Minar

unread,
Jan 25, 2012, 5:47:01 PM1/25/12
to Misko Hevery, ang...@googlegroups.com, Vojta Jina
Hmm...

I can think of 2 other solutions here but I'm not too crazy about any of them:

1) if possible reconfigure django to send the token as "XSRF-TOKEN" cookie and expect it to receive the token back as "X-XSRF-TOKEN" header
2) bypass DI and use window.document.cookie.match(/csrftoken=([^;]+)/)[1] to get access to the token in the config fn and set the default header


I think that we should make this more configurable so that you can specify the incoming cookie name and the outgoing header name.


Does anyone have a better suggestion?

/i

David Brunner

unread,
Jan 25, 2012, 11:46:09 PM1/25/12
to ang...@googlegroups.com
Igor,

Apologies if this is completely misguided, but why not make the default headers configurable through the $http service?  Then the headers could simply be set in the run function, without any call to config.  And, if the default headers needed to be changed for any reason, we could do that on the fly as necessary.

David

Misko Hevery

unread,
Jan 26, 2012, 12:19:34 AM1/26/12
to ang...@googlegroups.com
<stream of conciseness>
The original idea was that all of the configuration will be done in config phase in and run phase you would just access the object. We could allow you to access the providers from the run phase, but the issue is that of tho object is instantiated then it may no longer take configuration changes. But we could simply document that. My current thinking is to relax the requirements and allow run to access the providers, and document which property changes would translate at runtime.
</stream of conciseness>

-- Misko

David Brunner

unread,
Jan 26, 2012, 1:41:18 AM1/26/12
to ang...@googlegroups.com
Also stream of consciousness...

I don't yet fully understand the angular architecture, but it seems to me that the clean separation of config phase and run phase Misko describes is a nice simplifying constraint.  Provided that the config phase handles only properties that should be stable as long as the app runs, I can't see any problem.  However, it's not clear to me why default headers should necessarily be stable.  So, why not set the default headers through the service instead of through the provider?  The clean phase separation could be maintained.

Alternatively, I suppose one could simply endorse the workaround below, since it explicitly breaks the separation between the phases for a specific configuration object.

David

Sean Gilligan

unread,
Jan 26, 2012, 2:32:39 AM1/26/12
to ang...@googlegroups.com, Misko Hevery
On 1/25/12 9:19 PM, Misko Hevery wrote:
> <stream of conciseness>
> The original idea was that all of the configuration will be done in
> config phase in and run phase you would just access the object.

I'm wrestling with POST header configuration, too. I don't view http
headers as a configuration option. I view them as a parameter to each
and every call. Whether I'm doing it through $http (where it's easy) or
a $resource object where it is hard/impossible/poorly documented.

The assumption that everything is going to be 'application/json' or you
can override it in config is, in my opinion, not a good one. Often Ajax
developers don't have control of the server and it is not uncommon for
there to be a mixture of 'application/json' and
'application/x-www-form-urlencoded' content-types within the same app
and the same server. If there were an optional headers parameter that
could be defined for each $resource method, that would be the best
solution (for me) I think.


-- Sean

Vojta Jina

unread,
Jan 26, 2012, 4:09:05 PM1/26/12
to ang...@googlegroups.com, Misko Hevery
Yep, you should definitely be able to config headers per resource action. We need to add that: https://github.com/angular/angular.js/issues/736

It should be very easy to implement, so pull request more than welcomed...

V.

Sean Gilligan

unread,
Jan 27, 2012, 1:17:46 AM1/27/12
to ang...@googlegroups.com

Thanks for opening the issue. I'm OK for now because everything I'm
sending is form-encoded. If I do have to fix it, I'll submit a pull
request with the fix. (I do hope to get more involved with Angular.js
as I learn more and my schedule permits.)

-- Sean

bertol...@gmail.com

unread,
Feb 21, 2012, 4:40:44 AM2/21/12
to ang...@googlegroups.com, Misko Hevery
Hi,
I'm pretty new to angularjs but I already stumbled over this problem.
I tried to set HttpHeaders to content-Type application/json in my Controller.
In the docs they say you can change the headers through $httpProvider.
I tried by doing this in my controller:
$httpProvider.defaults.headers.post['Content-Type']= 'application/json';
and tried to inject httpProvider.
The problem is that httpProvider is not beeing injected.
Can you explain me how u were able to make it work with $http ?

Vojta Jina

unread,
Feb 21, 2012, 9:14:32 PM2/21/12
to ang...@googlegroups.com
You can get hold of providers only before run-time, so asking in controller is to late.

var module = angular.module('myApp', []);
module.config(function($httpProvider) {
  // do it here
});

V.

goodtaste

unread,
Aug 31, 2012, 6:14:55 AM8/31/12
to ang...@googlegroups.com
Hi guys,
is there any update on the topic?
Still cant get ajax request to work with Django's CSRF.

Any help would be great  

Cheers!

alaric....@gmail.com

unread,
Sep 6, 2012, 7:04:57 AM9/6/12
to ang...@googlegroups.com
I did it this way (not with Django) but since it's a common scenario maybe it can help :

My REST endpoints require a valid security token in headers, but the JS client needs to authenticate (with $http) to get a valid token. Basically the scenario for the first access :

1) login form is displayed

2) user submit the form, I use $http to submit the login/password to the authentication endpoint and, if they are correct, I get a tokenName and tokenValue couple. Ex : {tokenName:"X-XSFR-TOKEN", tokenValue:"...."}. Of course the authentication endpoint does not require the X-XSFR-TOKEN header to be present.

3) I add this header to the http headers, since a filter on the server intercepts requests to REST endpoints and check if this header is present and if the value matchs with a issued token.

    $scope.logIn = function () {
        $http.post('http://api.acme.com/authentication/authenticate?mailAddress=' + $scope.mailAddress + '&password=' + $scope.password)
            .success(function (response) {
                $scope.securityContext = response;
                $http.defaults.headers.common[$scope.securityContext.tokenName]=$scope.securityContext.tokenValue;
                $scope.password = null;
            });
    }
I keep the securityContext in $scope because I use ng-show="securityContext==null" to show the app or the loginForm on the main page.
Of course you might want to send password in a more secure way, it's just an example.

On the server it's easy to maintain a Map<String, User> that gives the user associated with a token so for each incoming request you can know 'who' (from a 'business' point of view) is the user.

And it would be easy to add SSO capabilities.

Adrien Pavillet

unread,
Apr 2, 2013, 1:48:45 PM4/2/13
to ang...@googlegroups.com
I dont know where you guys are with this but here's the solution for django-crsf and angular :

With module the name of the var containing your module.
Do not forget of course to add {% csrf_token %} to the form :)
then write :

module.config(["$httpProvider", function(provider) {
  provider.defaults.headers.common['X-CSRFToken'] = $('input[name=csrfmiddlewaretoken]').val();
  console.log($('input[name=csrfmiddlewaretoken]').val());
}]);


I thought i could leave it here for future problems !
Reply all
Reply to author
Forward
0 new messages