Разрешить CORS в Ruby on Rails

в своем config/application.rb файл, у меня есть этот код,

config.action_dispatch.default_headers = {
        'Access-Control-Allow-Origin' => '*',
        'Access-Control-Request-Method' => 'GET, PATCH, PUT, POST, OPTIONS, DELETE'
    }

но это не позволяет мне отправить почтовый запрос на маршрут по моему северу

Safari дает эту ошибку:

http://localhost:3000/studentsFailed to load resource: the server responded with a status of 404 (Not Found)
http://localhost:3000/studentsFailed to load resource: Origin http://localhost:4200 is not allowed by Access-Control-Allow-Origin.
localhost:1XMLHttpRequest cannot load http://localhost:3000/students. Origin http://localhost:4200 is not allowed by Access-Control-Allow-Origi

и в моей консоли сервера Rails:

Started OPTIONS "/students" for ::1 at 2015-03-28 21:00:45 -0500

ActionController::RoutingError (No route matches [OPTIONS] "/students"):

5 ответов


Я потратил некоторое время, работая над этим, и я могу сказать вам, что самое надежное решение-использовать стойки. смотри:https://github.com/cyu/rack-cors

Сначала добавьте драгоценный камень:

gem 'rack-cors', '~> 0.3.1'

потом в приложение.rb add

config.middleware.insert_before 0, "Rack::Cors" do
  allow do
    origins '*'
    resource '*', :headers => :any, :methods => [:get, :post, :options]
  end
end

я смог понять это с небольшой помощью из ответа @Akiomi:

в своем routes.rb, я добавил следующий код в верхней части файла:

  match '(:anything)' => 'application#nothing', via: [:options]

далее, в моем контроллере приложений, я добавил:

def nothing
    render text: '', content_type: 'text/plain'
end

вместе с заголовками в config/application.rb:

config.action_dispatch.default_headers = {
    'Access-Control-Allow-Origin' => '*',
    'Access-Control-Request-Method' => 'GET, PATCH, PUT, POST, OPTIONS, DELETE',
    'Access-Control-Allow-Headers:' => 'Origin, X-Requested-With, Content-Type, Accept'
}

да, обратите внимание на 'Access-Control-Allow-Headers:' => 'Origin, X-Requested-With, Content-Type, Accept' это не было включено в мой первоначальный вопрос, это одна из больших проблем.


добавить следующий код:

на config/routes.rb:

match 'students' => 'students#option', via: [:options]

на controllers/student_controller.rb:

def option
  render text: '', content_type: 'text/plain'
end

или вы можете использовать rack-cors.


в некоторых случаях браузер будет выполнять предпусковой запрос: вместо того, чтобы фактически выполнять запрос, он сначала выполняет запрос опций на тот же url-адрес, чтобы он мог узнать, каковы значения различных заголовков CORS (подробнее о предварительной подсветке здесь). Если этот запрос успешен и заголовки имеют правильные значения, он выполняет фактический запрос.

вы не добавили маршрут для этих запросов опций, поэтому они переходят на страницу rails 404, которая не включает заголовки CORS.

ответ OPTIONS просто должен установить те же заголовки CORS, которые вы обычно устанавливаете во время запроса. Он не должен делать ничего другого. Например

match 'students' => 'students#cors_preflight', via: [:options]

def cors_preflight
  render nothing: true
end

обратите внимание, что есть другие заголовки CORS, которые вам может потребоваться установить, например Access-Control-Allow-Credentials, Access-Control-Allow-Headers

когда у вас есть эта работа, вы можете рассмотреть вопрос о том, чтобы немного затянуть это - вы потенциально открываете свое приложение для межсайтовых атак сценариев.


вы можете разрешить происхождение из application_controller

class ApplicationController < ActionController::Base
  before_action :allow_cross_domain_ajax
  def allow_cross_domain_ajax
      headers['Access-Control-Allow-Origin'] = '*'
      headers['Access-Control-Request-Method'] = 'POST, OPTIONS'
  end
end