Skip to content
This repository

$resource should support custom http headers #736

Closed
vojtajina opened this Issue January 26, 2012 · 22 comments
Vojta Jina
Owner

when creating a resource definition it should be possible to define what headers should be sent along with the request when the action is invoked

Peter Andreas Moelgaard

What is the status on this one ?
It seems not be possible as of now, and I don't seem to be able to find it in the Trello Product Back Log...

I'm stuck right now, hoping to use the Resource abstraction, however I need to set the Authorization header and it seems to be extremely cumbersome to achieve this by using the Resource abstraction

Peter Andreas Moelgaard

it would be nice to be able to apply(override) all the params for the $http call in the $resource abstraction.... and not only pass in overrides to the parameters for the URL

Feature request ?

Max Martinsson maxmart referenced this issue from a commit in maxmart/angular.js May 17, 2012
Max Martinsson Fix for issue #736: ngResource now accepts headers c159b3d
robshep

Great stuff, we also need to pop in an "Authorization" header, Hopefully this will do the trick.

Max Martinsson maxmart referenced this issue from a commit in maxmart/angular.js June 05, 2012
Max Martinsson feat($resource): allow defining headers per action
Closes #736
5bec221
Tobias Florek

is there any activity here? this would be really nice to have.

Stephen Bronstein

+1! maybe @vojtajina wants @maxmart to merge his two commits into one commit with the desired commit format?

Miško Hevery mhevery closed this in 9b5656e September 04, 2012
Miško Hevery mhevery referenced this issue from a commit May 17, 2012
Max Martinsson feat(resource): accept headers
Closes #736
bc28a03
Miško Hevery mhevery referenced this issue from a commit in mhevery/angular.js May 17, 2012
Max Martinsson feat($resource): support custom headers per action
Closes #736
f6d7493
floydsoft floydsoft referenced this issue from a commit September 18, 2012
Commit has since been removed from the repository and is no longer available.
Ineffective

I tried using this feature (custom headers) in my current project but cannot seem to get it to work. I have it on Github here:
https://github.com/Ineffective/Steak-Mobile
and the method which tries to use the custom header functionality is in line 31 here:
https://github.com/Ineffective/Steak-Mobile/blob/master/src/main/webapp/app/services.js

I tried adding a header for authorization as well as trying to tell the server that i want json as a response (default is xml)

I used v.1.0.1, 1.0.2 and 1.1.0, none seem to support it? Any hints on why it's not working would be greatly appreciated

Luis Ramón López

I don't know for sure, but it seems that the feature landed two months ago into the 1.0.x branch (b936e52), but 8 hours ago that feature was removed as it adds a new feature into a stable branch (look here: 29541e7).

I suppose that custom headers will be still available on master. Did you try to download and build the current master?
You can follow the instructions from the "Checking Out and Building Angular" section in http://docs.angularjs.org/misc/contribute

Ineffective

I guess I could also just use the lower level $http since there it should be possible to add a custom header right? I'll follow those instructions you provided but I don't understand why the feature was taken out again a few hours ago?
Could you elaborate why they would take such an important feature out again?

Pawel Kozlowski
Collaborator

@Ineffective it was just remove from the bug-fix branch (1.0.x), it is still in master and will be released in version of 1.1.x.

It was taken out from the bug-fix branch since it was committed in there by accident, this branch should only have bug fixes and no new features.

The actual fix is still in master, if you want to test it you can grab the latest build from master: http://ci.angularjs.org/view/AngularJS/job/angular.js-angular-master/ws/build/

Be warned thought, it is just a SNAPSHOT build so it is not the same stability as the released version. Should be good for dev thought.

Ineffective

I just created my own build (v.1.1.1) and included those two files (angular.js and resource.js) into my project. Still my custom headers don't show in the dev tools (chrome). I see my GET request, but I get a 401 HTTP Error back and I cannot see my headers.
This really bugs me. I can see the implementaiton of custom headers in the resource.js source code but they won't be added to my request sent

Ineffective

I think I might have found something:

I debugged into the source code and found the following: (found in Angular 1.0.1 angular.js)

function createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {
  // TODO(vojta): fix the signature
  return function(method, url, post, callback, headers, timeout, withCredentials, responseType) {
    $browser.$$incOutstandingRequestCount();
    url = url || $browser.url();

    if (lowercase(method) == 'jsonp') {
      var callbackId = '_' + (callbacks.counter++).toString(36);
      callbacks[callbackId] = function(data) {
        callbacks[callbackId].data = data;
      };

      jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),
          function() {
        if (callbacks[callbackId].data) {
          completeRequest(callback, 200, callbacks[callbackId].data);
        } else {
          completeRequest(callback, -2);
        }
        delete callbacks[callbackId];
      });
    } else {
      var xhr = new XHR();
      xhr.open(method, url, true);
      forEach(headers, function(value, key) {
        if (value) xhr.setRequestHeader(key, value);
      });

my method is specified as jsonp, since the code lies locally on my hard drive and the request is being made to a REST Service provided by our companies servers. so it executes the code in the if(..){...} block

Here is a screenshot that shows my debugging status:

http://img404.imageshack.us/img404/9101/screengithub.png

Why aren't the headers passed along with the rest in the

completeRequest(callback, 200, callbacks[callbackId].data);

method? This is where my headers get lost i think. However idk why this only applies to me and not to any http request with custom headers. Is it because my request is 'jsonp' ?

Ineffective

Okay so I talked to one of our seniors and he told me about the general principle of cross domain AJAX and its implications when trying to access another server through javaScript. Good for securitys sake, bad for me, since I need to either implement CORS or set up a proxy servlet on my jetty which forwards all requests to my actual backend and then returns its answers. Anyways what I learned is, it wasn't my fault, it's just that JSONP doesn't let me. damn java development experience...didnt teach me this ;)

Maybe you could include somewhere in the documentation a disclaimer saying "NOTE: NO CUSTOM HEADERS POSSIBLE WITH JSONP" or something. So that others won't go crazy about the same stuff i just did

Hitesh Joshi

Hello.. How do I override the headers? I am doing this,

               return $resource(api+'users/login',{},{
                                login:{
                            method:'POST',
                        isArray:true,
                        params : {login:'iamhitesh',password:'hitesh180'},
                            headers:
                        {
                            'Content-Type': 'application/x-www-form-urlencoded',
                                            'X-Mcf-Client' : 'web'

                            }
                        }
          })

but the content-type headers are always application/xml .. why?

Amir Souchami

Did you try:
$http.defaults.headers.common['Content-Type'] = 'application/x-www-form-urlencoded';
just found it out now.. :)

Calvin Froedge

I just built from 1.1.2-7dff7bb6 and was unable to change default headers to application/json

Calvin Froedge

Got it! Set in $httpProvider defaults.

Romain Lefrancois

Got it! Set in $httpProvider defaults.

Like this :

.config(function($httpProvider) {
    $httpProvider.defaults.headers.post  = {'Content-Type': 'application/x-www-form-urlencoded'};
})
Miša Mаkaröv

What if I have different headers for different resources?

iQuarK

You can define the header for each resource:

$resource(
      $rootScope.routes.route1 + ':uri/:action/',
      {},
      {
        resource1: {
          method: 'GET',
          params: {uri: $rootScope.api_services.service1},
          headers: {'Authorization':'Bearer '+User.getAccessToken()}
        },
        resource2: {
          method: 'GET',
          params: {
            uri: $rootScope.api_services.service2,
            action: $rootScope.api_services.action2
          },
          headers: {'Authorization':'Bearer '+User.getAccessToken()}
        }
      }
)
Kamil Augustynowicz

Hi all,
I tried to make a request like:

angular.module("app").factory "Query", ($resource) ->
  $resource(
    API_URI + "query/:id",
    { id: "@id" },
    {
      getAll: {
        method: "POST",
        isArray: true,
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
        }
      }
    }
  )

but it doesn't sets the header right. I still get the Content-Type 'application/json'.
I want to set it only for the action getAll() not as default. Maybe someone can help (I'm using angular version 1.2.3)

John Reading

^ same. What up with that?

John Reading

Turns out $resource doesn't roll with the only solution. You need to use the $http lower level methods and set the header to undefined so that Angular can set the boundary (transformRequest).

    $scope.uploadFile = function(file){
        var formData = new FormData();
        formData.append('file', file);

        $http({
            method: 'POST',
            url: 'the/url/to/accept/the/file',
            data: formData,
            headers: { 'Content-Type': undefined },
            transformRequest: function(data) { return data; }
        });
    };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.