Ember.js ember-data restadapter не загружает json
Ура!
У меня есть хранилище данных ember:
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 или что?
UPDATE:
В контроллере приложения на стороне сервера:
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.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 с правильными заголовками
Ответы
Ответ 1
RESTAdapter
ожидает JSON
, это не проблема, но страница и json не находятся в одном домене, это проблема безопасности. Вы можете решить это, используя одно из двух решений, названных ниже.
Вы работаете в той же политике происхождения, вы должны либо использовать JSONP
, либо CORS
. Самое быстрое исправление, вероятно, должно было бы указывать данные ember-данных, которые вы хотите использовать JSONP
.
Для CORS
ваш сервер должен ответить на запрос OPTIONS
заголовками:
-
Access-Control-Allow-Origin
-
Access-Control-Request-Method
Я не эксперт по rails, но вам, вероятно, понадобится что-то сделать с драгоценным камнем 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);
},
})
});
Ответ 2
У меня есть простая работа в Rails (которая работает для меня до сих пор.) Это неряшливо, как есть, но может легко быть затянуто логикой в контроллерах.
В routes.rb
:
match ':path' => 'authentications#allow', constraints: {method: 'OPTIONS'}
который просто возвращает статус OK
любому запросу OPTIONS
.
def allow
head :ok
end
И затем в application_controller.rb
установите заголовки совместного использования ресурсов Cross-origin (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
Ответ 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