干杯!
我有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试图加载旅游资源,而不是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请求
该 RESTAdapter
预计 JSON
这不是问题,但页面和json不在同一个域上,这是一个安全问题。您可以使用以下两种解决方案之一来解决此问题。
你正在跑进去 同源政策 你应该使用 JSONP
要么 CORS
。最快的修复方法可能是告诉你要使用的ember-data JSONP
。
对于 CORS
您的服务器需要响应 OPTIONS
请求标题:
Access-Control-Allow-Origin
Access-Control-Request-Method
我不是专家,但你可能需要对宝石做点什么 rack-cors
看到 这里 要么 这里。
你可以通过覆盖它来做到这一点 ajax
挂在 RESTAdapter
像这样:
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);
},
})
});
我在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
如果您希望使用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