Passing header information to REST Get request using RESTAdapter

I am trying to send a Get request to my client server using the RESTAdapter, and I am required to pass an AuthToken along with the request (as a header param) in order to be authorized. I’ve tested the Get request with AuthToken using Chrome Postman and it works just fine, but using the code below I always get error 401 unauthorized, can someone please tell me what I am doing wrong and how to send the AuthToken? Thanks

App.store = DS.Store.create({
    revision: 11,
    adapter: DS.RESTAdapter.extend({
        url: "http://api.clientdomain.com",
        headers: { 
           'Accept': 'application/json',
           'AuthToken': '58jdc60b-c891-9981-8821-939p0121609b'
        },
        ajax: function (url, type, hash) {
            hash.url = url;
            hash.type = type;
            hash.dataType = 'jsonp';
            hash.contentType = 'application/json';
            hash.context = this;

            if (hash.data && type !== 'GET') {
                hash.data = JSON.stringify(hash.data);
            }

            jQuery.ajax(hash);
        },
    })
});

You can actually do this.

$.ajaxSetup({
    headers: { 'x-my-custom-header': 'some value' }
});

This set headers for all requests.

1 Like

or you can do it ember way.

DS.RESTAdapter.reopen({
  headers: { 
    "Accept": "application/json, text/javascript; q=0.01"
  }
});

@jamalsoueidan I’ve already tried doing it the ember way as shown in my question but it didn’t work…it returns error 401.

One thing thought not sure if it will make a difference (please excuse my ignorance), the API documentation include a call for authentication where I should send a payload to get the AuthToken which I’ve used in my Get request. But I am not sure if this is necessary as I’ve tried using Chrome Postman to process the Get request without first authenticating with payload and it worked just fine…make sense?

Are you sure you have the correct ember-data version?

@jamalsoueidan I am not using the latest, I am using ember-1.0.0-rc.1 when I tried upgrading to latest, I got tons of errors. Do I have to use latest version?

I am also having this issue. The Ember way doesn’t seem to work for me. When I do this:

DS.RESTAdapter.reopen({
  headers: { 
    "Accept": "application/json, text/javascript; q=0.01"
  }
});

All the standard headers are removed and it uses the OPTIONS method instead of GET. On top of that the headers I have added never actually appear in the request headers.

I have found that adding headers does, in fact, add the headers unless there is also a host defined. I am using the latest version of Ember Data.

Looking at the RESTadapter the ajaxOptions method is what actually adds the headers. This is called by the ajax method. None of this seems to rely on the existence of a host.

@mchan do you also have a host defined? @jamalsoueidan does this shine some light? I’m trying to work this out still.

I have successfully used this approach:

Ember.$.ajaxPrefilter(function(options, oriOpt, jqXHR) {
    jqXHR.setRequestHeader("someHeader", "someValue");
});

This approach allows you to dynamically change the header/value on the fly rather than being statically defined once, depending on your needs.

This has the same effect for me. It works great unless I set a host. As soon as I set a host the headers are lost.

Headers worked for me in the following way:

App.store = DS.Store.create({
  adapter: 'application'	
});
App.ApplicationAdapter = DS.RESTAdapter.extend({
    headers: {
	"header" : "myheader"
    }
});
DS.RESTAdapter.reopen({
    host: 'http://localhost',
});

I have not gotten any of these methods to work inserting headers with a host.

Defining the host seems to cancel out the insertion of the headers as well as change the request method to OPTIONS rather than GET.

Headers can be a computed property as of 1.0.0-beta.8.

// app/adapters/application.js

export default DS.ActiveModelAdapter.extend({
  headers: Ember.computed(function(){
    var token = Ember.$('meta[name="csrf-token"]').attr('content');

    return {"X-CSRF-Token": token};
  })
});
3 Likes

I just tried your solution @rwjblue, but it still changes my request method to OPTIONS and does not add the new headers.

// app/adapters/application.js

import DS from 'ember-data';

export default DS.ActiveModelAdapter.extend({
	host: 'https://api.example.com',
	headers: Ember.computed(function(){
		return {"APIKEY": "abc123"};
	});
});
  • Ember: 1.7.0
  • Ember-CLI: 0.0.41
  • node: 0.10.31
  • npm: 1.4.24

The OPTIONS request is likely a result of CORS (not ember-data directly).

1 Like

So do I need to configure OAuth to handle CORS as described here even though I am not using ember-simple-auth:

This just does not seem to be working. I’ve tried the examples that were given in the documentation to no avail. If I hard-code it without the function, they are inserted. If I try to make it dynamic - the code inside never executes (verified by logging to the console). Even if it isn’t dynamic like the examples, they don’t get added to the headers:

App.ApplicationAdapter = DS.RESTAdapter.extend({
	headers: function(){
		return {
			Authorization: 'CuzISaySo',
			Project: 'MyAwesomeProject',
		};
	}
});

I have validated that my CORS header is set to accept them. Not sure what else to do; seems like a bug due to the delta in behavior between the documentation and my real-world experience.

Ember      : 1.7.0 
Ember Data : 1.0.0-beta.5 
Handlebars : 1.3.0
jQuery     : 2.0.3 

I am almost positive the options header is sent from the browser itself because of the cross domain request. It does this to make sure that the requested domain has a cors policy to allow your current domain to make the request. If the response to the options request contains a valid cors policy the browser will then send the xhr request that you crafted. There is likely something wrong with your cors policy if your intended xhr request never makes it through.

I was having this same issue and none of the above solutions fixed it. Turns out if you are sending an ajax/XHR request to a different domain, your browser will automatically send a “preflight” HTTP OPTIONS request before sending your actual request.

So, as other folks alluded, your backend has to respond to that preflight correctly before the browser will send the actual request with your custom headers.

Here’s what happened to me- my backend responded to the preflight request with the right headers and a 401 code (because the requested route required authorization). My browser decided to respond by sending the real request without my custom headers. So, it APPEARED that my browser had accepted the preflight response, but in reality it had not. I had to make sure my backend responded to the preflight request with a 200 code, that fixed my problem! Now my browser responds with the actual request and no longer discards my custom headers.

1 Like