Rails在CORS预检选项请求中响应404

我使用Rails 4创build了一组服务,我正在使用JavaScript浏览器应用程序。 交叉原点GETS工作正常,但我的POST失败了预检选项检查404错误。 至less,我想这就是发生了什么事情。 这些错误出现在控制台中。 这是Mac上的Chrome 31.0.1650.63。

OPTIONS http://localhost:3000/confessor_requests 404 (Not Found) jquery-1.10.2.js:8706 OPTIONS http://localhost:3000/confessor_requests No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access. jquery-1.10.2.js:8706 XMLHttpRequest cannot load http://localhost:3000/confessor_requests. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access. main.html:1 

我已经search了高和低的指示启用CORS,我很难过。 通常的build议似乎是把这样的东西放在应用程序控制器,我做了。

 before_filter :cors_preflight_check after_filter :cors_set_access_control_headers def cors_set_access_control_headers headers['Access-Control-Allow-Origin'] = '*' headers['Access-Control-Allow-Methods'] = 'POST, PUT, GET, OPTIONS' headers['Access-Control-Allow-Headers'] = '*' headers['Access-Control-Max-Age'] = "1728000" end def cors_preflight_check if request.method == :options headers['Access-Control-Allow-Origin'] = '*' headers['Access-Control-Allow-Methods'] = 'POST, PUT, GET, OPTIONS' headers['Access-Control-Allow-Headers'] = '*' headers['Access-Control-Max-Age'] = '1728000' render :text => '', :content_type => 'text/plain' end end 

随后是routes.rb中的某种路由,当OPTIONS请求进入时将redirect到此操作。

 match "/*all" => "application#cors_preflight_check", :constraints => { :method => "OPTIONS" } 

“匹配”指令不再适用于Rails 4,所以我摆弄它,试图直接匹配POSTS,如下所示:

 post "/*all" => "application#cors_preflight_check", :constraints => { :method => :options } 

但它仍然不起作用。 由于GET请求正在工作,我假设我缺less的是OPTIONS请求的正确路由。 不过,我已经尝试了所有我能想到的路线,似乎没有任何东西能让请求通过。

我也尝试安装cyu / rack-cors ,这给出了相同的结果。

任何人都知道我在做什么错了?

这是一个与机架gem的解决scheme,你说你试过了。 正如其他人所提到的,关于您使用的前端框架以及实际请求的外观,您没有提供太多细节。 所以以下可能不适用于你,但我希望它可以帮助别人。

在我的情况下,gem工作正常,直到我使用PUT(或补丁或删除)。

如果你看看你的浏览器开发者控制台,看看请求标题,你应该有这样一行:

 Access-Control-Request-Method: PUT 

重要的是要注意的是,你传递给resourcemethodsAccess-Control-Request-Method ,而不是在飞行前检查之后的请求方法。

请注意我有:methods => [:get, :post, :options, :delete, :put, :patch]将包含我所关心的所有方法。

因此,您的整个configuration部分应该看起来像这样,为development.rb

 # This handles cross-origin resource sharing. # See: https://github.com/cyu/rack-cors config.middleware.insert_before 0, "Rack::Cors" do allow do # In development, we don't care about the origin. origins '*' # Reminder: On the following line, the 'methods' refer to the 'Access- # Control-Request-Method', not the normal Request Method. resource '*', :headers => :any, :methods => [:get, :post, :options, :delete, :put, :patch], credentials: true end end 

使用Rails 3.2.11。

我放

 match '*path', :controller => 'application', :action => 'handle_options_request', :constraints => {:method => 'OPTIONS'} 

在我的routes.rb文件中。 关键是把它作为最重要的(在routes.rb文件的顶部)。 创build该行为以便公开可用:

  def handle_options_request head(:ok) if request.request_method == "OPTIONS" end 

并在应用程序控制器中的filter

  after_filter :set_access_control_headers def set_access_control_headers headers['Access-Control-Allow-Origin'] = '*' headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE' end 

是的,正如其他人指出的那样,创业板也许可以做得更好。 但是,因为我非常喜欢用cors代码在原始博客文章中指出的方法,所以如果您使用该代码,我已经find了Rails 4解决scheme。

在您的routes.rb中:

 match '*all' => 'my_method_name#cor', via: :options 

在你的my_method_name控制器中:

 def cor # blank section for CORR render :text => '' end 

只要你有加上你的其他代码:

 before_filter :cors_preflight_check after_filter :cors_set_access_control_headers ... 

那么你应该为Rails 4设置。

也许这个要点可以帮助你: CORS in Rails 4 APIs

它将OPTIONS方法添加到路由定义中,并向API基本控制器添加一个filter,以直接响应带有正确头的OPTIONS请求,并为所有其他操作设置正确的CORS头。

用Rails 4和Devise来解决这个问题。 我最终使用了Calvin Yu的Rack CORS middleware 。 一个伟大的免费博客文章 。

我不确定你使用的是什么JavaScript前端框架(或者如果你是),因为你没有详细说明你在客户端连接到Rails 4 API的过程,但是我想添加我的答案,以帮助任何人的情况下。

从AngularJS前端连接到Rails 4 API与Devise gem(都在单独的本地主机端口上运行)时,遇到了完全相同的问题。 我正在尝试使用来自AngularJS窗体的POST请求login到后端,但我一直得到一个404 NOT FOUND错误,因为我正在发送带有预检的OPTIONS请求。 花了两天多的时间才弄清楚如何解决这个问题。

基本上,您需要为您的前端(Angular,Backbone,无论)设置一个代理服务器,以便连接到您的API,以便您的前端认为请求使用相同的来源。 有一些简单的解决scheme用于使用GruntJS来设置代理。 我使用Gulp-Connect和proxy-middleware来为我的项目使用Gulp,并使用以下设置(基于此处的解决scheme):

 var gulp = require('gulp'), connect = require('gulp-connect'); gulp.task('devServer', function() { connect.server({ root: './dist', fallback: './dist/index.html', port: 5000, livereload: true, middleware: function(connect, o) { return [ (function() { var url = require('url'); var proxy = require('proxy-middleware'); var options = url.parse('http://localhost:3000/'); options.route = '/api'; return proxy(options); })() ]; } }); }); 

我希望这可以帮助别人!

我遇到了同样的问题,目前正在评估以下路由,以解决任何可能的安全/性能问题。 他们解决了这个问题,但…

 match '/', via: [:options], to: lambda {|env| [200, {'Content-Type' => 'text/plain'}, ["OK\n"]]} match '*unmatched', via: [:options], to: lambda {|env| [200, {'Content-Type' => 'text/plain'}, ["OK\n"]]} 

尽pipe“匹配”可能不适用于Rails 4,但如果将其限制为特定的方法,则显然可行