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