在 Rails 的 Ruby 中允许 CORS

Allow CORS in 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'
    }

但这不允许我向服务器上的路由发送 post 请求

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"):

添加以下代码:

config/routes.rb中:

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

controllers/student_controller.rb中:

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

或者您可以使用 rack-cors.

在@Akiomi 的回答的帮助下,我能够解决这个问题:

在我的 routes.rb 中,我在文件顶部添加了以下代码:

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

接下来,在我的应用程序控制器中,我添加了:

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

config/application.rb 中的 headers 一起:

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' 未包含在我的原始问题中,这是大问题之一。

在某些情况下,浏览器会执行预检请求:它不是实际执行请求,而是首先对相同的 url 执行 OPTIONS 请求,以便它可以找出各种 CORS 的值headers 是(更多关于预检 here)。如果此请求成功并且 headers 具有正确的值,则它会执行实际请求。

您还没有为这些选项请求添加路由,因此它们将进入 rails 404 页面,该页面不包含 CORS headers。

OPTIONS 响应只需设置与您通常在请求期间设置的相同的 CORS headers。它不应该做任何其他事情。例如

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

def cors_preflight
  render nothing: true
end

请注意,您可能需要设置其他 CORS headers,例如 Access-Control-Allow-CredentialsAccess-Control-Allow-Headers

当你完成这项工作后,你可能希望考虑稍微收紧它 - 你可能会打开你的应用程序以进行跨站点脚本攻击。

我花了一些时间研究这个,我可以告诉你最可靠的解决方案是使用 rack-cors。参见:https://github.com/cyu/rack-cors

首先添加gem:

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

然后在application.rb中添加

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

如果您的生产应用程序不提供静态资产(例如,如果您使用像 nginx 或 apache 这样的服务),请考虑将上例中的 ActionDispatch::Static 替换为 0。有关参数的更多信息,请参阅 https://github.com/cyu/rack-cors#common-gotchas

Rails 5

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