Ember.js ember-data restadapter无法加载json

时间:2013-02-12 08:36:13

标签: javascript json ember.js ember-data

干杯! 我有ember-data store:

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

路由器:

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

我从远程服务器接收此JSON:

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

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

但是当我尝试return TravelClient.Tour.find()时,它失败了:

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.

看起来好像RESTAdapter不知道它必须接收JSON还是什么?

更新

在rails服务器端的应用程序控制器中:

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

但它仍然是:

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

看起来RESTAdapter试图加载旅游资源,而不是tour.json:

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

工作解决方案

扩展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";
  }
})

并使用正确的标题

回复OPTIONS请求

3 个答案:

答案 0 :(得分:10)

RESTAdapter期望JSON不是问题,但页面和json不在同一个域上,这是一个安全问题。您可以使用以下两种解决方案之一解决此问题。

您已经遇到了same origin policy,您应该使用JSONPCORS。最快的解决方法可能是告诉您要使用的{4}的ember-data。

对于JSONP,您的服务器需要使用标头响应CORS请求:

  • OPTIONS
  • Access-Control-Allow-Origin

我不是专家,但您可能需要对gem Access-Control-Request-Method做一些事情,请参阅herehere

您可以通过覆盖rack-cors中的ajax挂钩来实现这一点:

RESTAdapter

答案 1 :(得分:1)

我在Rails中有一个简单的解决方法(到目前为止这对我有用。)它是不整洁的,但可以很容易地用控制器中的逻辑来收紧。

routes.rb

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

只会将状态OK返回给任何OPTIONS请求。

def allow
  head :ok
end

然后在application_controller.rb中为每个请求设置跨源资源共享(CORS)标头:

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

答案 2 :(得分:1)

如果您希望使用JSONP,则可以更轻松地覆盖私有ajaxOptions函数,而不是使用jQuery并覆盖ajax方法。 Ember的管道包括删除jQuery依赖项。所以这样做:

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

如果Ember核心团队可以公开一种公共方法来正式支持这一点(而不是破解私人api),那将是创造。

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