Ember.js ember-data restadapter fail to load json

xamenrax picture xamenrax · Feb 12, 2013 · Viewed 10.5k times · Source

Cheers! I have ember-data store:

TravelClient.Store = DS.Store.extend({
  revision: 11,
  adapter: DS.RESTAdapter.create({ bulkCommit: false, url: "http://someIP:somePORT"})
});

And router:

TravelClient.ToursRoute = Ember.Route.extend({
  model: function() {
    return TravelClient.Tour.find();
  }
});

I recieve this JSON from remote server:

{
  "tours": [
    {
      "id": "5110e8b5a8fefe71e0000197",
      "title": "qui deserunt dolores",
      "description": "Id velit nihil.",
      "seats": 12,
      "options": [

      ],
      "images": [
        {
          "id": "5110e8b5a8fefe71e0000196",
          "url": "url"
        }
}

But when I try to return TravelClient.Tour.find() it fails with:

http://someIP:somePORT/tours 404 (Not Found)

XMLHttpRequest cannot load http://someIP:somePORT/tours. Origin http://localhost:3000 is not allowed by Access-Control-Allow-Origin.

IT seems like RESTAdapter doesn't know, that it must receive JSON or what?

UPDATE:

In the application controller on the rails server-side:

def set_access_control_headers
  headers['Access-Control-Allow-Origin'] = '*'
  headers['Access-Control-Request-Method'] = '*'
end

But it's still :

OPTIONS http://someIP:somePORT/tours 404 (Not Found)

And it looks like RESTAdapter tries to load tours resource, not tours.json:

Request URL:http://someIP:somePORT/tours

WORKING SOLUTION

Extend RESTAdapter:

TravelClient.CUSTOMAdapter = DS.RESTAdapter.extend({
  bulkCommit: false, 
  url: "http://remote_server_address",    
  buildURL: function(record, suffix) {
    var s = this._super(record, suffix);
    return s + ".json";
  }
})

and respond to an OPTIONS request with right headers

Answer

albertjan picture albertjan · Feb 12, 2013

The RESTAdapter expects JSON that is not the problem but the page and the json are not on the same domain, this is a security issue. You can resolve this by using one of the two solutions named below.

You're running into the same origin policy you should either use JSONP or CORS. The quickest fix would probably be to tell ember-data that you want to use JSONP.

For CORS your server needs to respond to an OPTIONS request with the headers:

  • Access-Control-Allow-Origin
  • Access-Control-Request-Method

i'm no rails expert but you will probably need to do something with the gem rack-cors see here or here.

You could do that by overriding the ajax hook in the RESTAdapter like so:

App.store = DS.Store.create({
    revision: 11,
    adapter: DS.RESTAdapter.create({
        namespace: "data",
        url: "",
        ajax: function (url, type, hash) {
            hash.url = url;
            hash.type = type;
            hash.dataType = 'jsonp';
            hash.contentType = 'application/json; charset=utf-8';
            hash.context = this;

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

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