最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Ember.js ember-data restadapter fail to load json - Stack Overflow

programmeradmin0浏览0评论

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

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

Share Improve this question edited Feb 12, 2013 at 11:07 xamenrax asked Feb 12, 2013 at 8:36 xamenraxxamenrax 1,7443 gold badges27 silver badges48 bronze badges 3
  • the headers you set are returned with the GET request you need to return them with an OPTIONS request – albertjan Commented Feb 12, 2013 at 9:46
  • Rack CORS gem did the trick, thanks. I think it's doing all that stuff with OPTIONS requests just "out of the box". – xamenrax Commented Feb 12, 2013 at 11:03
  • Heres the link for the next visitor github.com/cyu/rack-cors ftw – genkilabs Commented Aug 30, 2013 at 20:54
Add a comment  | 

3 Answers 3

Reset to default 10

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);
        },
    })
});

I have a simple work around in Rails (that is working for me so far.) It is untidy as is, but can easily be tightened up with logic in the controllers.

In routes.rb:

match   ':path' => 'authentications#allow', constraints: {method: 'OPTIONS'}

Which simply returns status OK to any OPTIONS request.

def allow
  head :ok
end

And then in application_controller.rb set the Cross-origin resource sharing (CORS) headers for every request:

before_filter :cors
def cors
  response.headers.merge! 'Access-Control-Allow-Origin' => '*', 'Access-Control-Allow-Methods' => 'POST, PUT, GET, DELETE', 'Access-Control-Allow-Headers' => 'Origin, Accept, Content-Type'
end

If you are looking to use JSONP it's much easier to override the private ajaxOptions function instead of using jQuery and overriding the ajax method. Ember's pipeline includes the removal of the jQuery dependency. So do this instead:

adapters/application.js:

import DS from 'ember-data';

export default DS.RESTAdapter.extend({
    ajaxOptions: function(url, type, options) {
        var hash = this._super(url, type, options);
        hash.dataType = "jsonp";
        return hash;
    }
});

It would be create if the Ember core team could expose a public method to officially support this (instead of hacking a private api).

https://github.com/emberjs/data/blob/1.0.0-beta.15/packages/ember-data/lib/adapters/rest_adapter.js#L915

发布评论

评论列表(0)

  1. 暂无评论