【问题标题】:Ember.js ember-data restadapter fail to load jsonEmber.js ember-data 恢复适配器无法加载 json
【发布时间】:2015-02-23 05:45:04
【问题描述】:

干杯! 我有 ember-data 存储:

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 尝试加载 tours 资源,而不是 tours.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 请求

【问题讨论】:

  • 您设置的标头随GET 请求返回,您需要使用OPTIONS 请求返回它们
  • Rack CORS gem 成功了,谢谢。我认为它通过“开箱即用”的 OPTIONS 请求完成所有这些工作。
  • 这是下一位访问者的链接github.com/cyu/rack-corsftw

标签: javascript json ember.js ember-data


【解决方案1】:

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

您遇到了same origin policy,您应该使用JSONPCORS。最快的解决方法可能是告诉 ember-data 你想使用JSONP

对于CORS,您的服务器需要响应带有标头的OPTIONS 请求:

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

我不是 Rails 专家,但您可能需要使用 gem rack-cors 做一些事情,请参阅 herehere

您可以通过覆盖RESTAdapter 中的ajax 挂钩来做到这一点,如下所示:

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

【讨论】:

  • 要使用 CORS,我只需在服务器的响应标头中添加 Access-Control-Allow-Origin: * 之类的东西?
  • 是的,请参见此处:en.wikipedia.org/wiki/Cross-origin_resource_sharing 和此处:developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS 还有一些其他标头您可以更具体地控制允许的内容。
  • Rack CORS gem 只是为了更具体的定制——不是我目前需要的,但感谢您的关注。
  • 您需要以某种方式响应带有标头的 OPTIONS 请求。
  • 但是我的服务器响应了一个 OPTIONS 请求,我有正确的响应头。
【解决方案2】:

我在 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

【讨论】:

  • 但是我的标题没有问题,只是 Rails 给了我 html,而我需要 json。所以解决方法就是直接对 Rails 说你想要 json - 扩展适配器的 buildURL 方法。对不起我的英语。
【解决方案3】:

如果您希望使用 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-07-20
    • 1970-01-01
    • 1970-01-01
    • 2016-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多