如何在Rails 4应用程序中启用CORS

26

我快要抓狂了...自早上以来,我一直在尝试在这个Rails应用程序中启用CORS,但它就是不起作用。我已经尝试过 这个、使用 Rack Cors Gem这个答案 和这篇 文章,但都没有成功。

有人可以指点我正确的方向吗?

这是我的js代码:

      var req = new XMLHttpRequest();

      if ('withCredentials' in req) {
            // req.open('GET', "https://api.github.com/users/mralexgray/repos", true);
            req.open('GET', "http://www.postcoder.lc/postcodes/" + value, true);
            // Just like regular ol' XHR
            req.onreadystatechange = function() {
                if (req.readyState === 4) {
                    if (req.status >= 200 && req.status < 400) {
                        // JSON.parse(req.responseText) etc.
                        console.log(req.responseText);
                    } else {
                        // Handle error case
                    }
                }
            };
            req.send();
        }
当我尝试访问这个URL(通过一个外部客户端):https://api.github.com/users/mralexgray/repos ,它可以正常工作,所以我认为问题是出在我的Rails API上。我错了吗?
编辑:目前在我的控制器中有这个内容:
skip_before_filter :verify_authenticity_token
before_filter :cors_preflight_check
after_filter :cors_set_access_control_headers

# For all responses in this controller, return the CORS access control headers.
def cors_set_access_control_headers
  headers['Access-Control-Allow-Origin'] = '*'
  headers['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS'
  headers['Access-Control-Max-Age'] = "1728000"
end

# If this is a preflight OPTIONS request, then short-circuit the
# request, return only the necessary headers and return an empty
# text/plain.

def cors_preflight_check
  headers['Access-Control-Allow-Origin'] = '*'
  headers['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS'
  headers['Access-Control-Allow-Headers'] = 'X-Requested-With, X-Prototype-Version'
  headers['Access-Control-Max-Age'] = '1728000'
end

我已经尝试过了,但没有成功。我甚至使用了示例应用程序,但仍然没有运气。 - WagnerMatosUK
1
你曾经让它工作过吗?我有一个使用Angular前端进行调用的应用,我也尝试了所有的解决方案。但是rack cors gem对我无效。 - Ka Mok
3个回答

39

你应该使用rack cors

它提供了一个很好的DSL,可以在config/application.rb中使用,而不需要处理混乱的标头和前置过滤器。

一个非常宽松的设置如下,但当然,你需要稍微调整一下:

use Rack::Cors do
  allow do
    origins '*'
    resource '*', headers: :any, methods: :any
  end  
end

你是指 config/application.rb 文件吗? - WagnerMatosUK
我不知道“它没用”是什么意思 :) 我在我的应用程序中使用它,一切都很好。你有更多的信息吗? - apneadiving
好的,现在它在Chrome上运行正常。我认为问题是权限的种类。有趣的是它在FF和Safari上不起作用。我猜这与Rails无关,而是与JS有关? - WagnerMatosUK
是的,也许可以尝试使用这个客户端:https://github.com/mapbox/corslite/ 它旨在跨浏览器使用,但不幸的是只适用于GET请求。 - apneadiving
1
请问您可以解释一下“当然,您需要稍加改进”吗?它为什么重要,我们应该如何做到呢? - Aleksandrus
我有一个类似的设置,但已指定允许的来源列表,但仍然遇到此错误:跨源资源共享错误:preflightInvalidAllowCredentials。我正在检查请求并查看响应标头中的Access-Control-Allow-Origin是否与请求标头中的Origin匹配。有什么见解吗? - Matt

21

Rack::Cors 提供了跨域资源共享的支持。

启用 rackcors 的步骤:

  1. 将以下 gem 添加到你的 Gemfile 中:

    gem 'rack-cors'

  2. 将以下代码添加到 config/application.rb 文件中:

如果你正在使用 Rails 3/4:

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

如果您正在使用Rails 5:

config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins '*'
    resource '*', headers: :any, methods: :any
  end
end

1
很好的解释!!! 对我来说非常有用和值得。谢谢。 - Jahnavi Sananse

2

以下是对我有效的方法:

  1. 在Gemfile中添加以下内容:gem 'rack-cors',然后运行bundle install

  2. 创建一个新文件/config/initializers/cors.rb

  3. 在该文件中添加以下内容:

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

就是这样!

顺便提一下,这些说明直接来自这里


2
我正在使用:resource '*',headers: :any,methods: :any - mahfuz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接