rails api,react前端,axios,开发中的CORS不起作用

Posted

技术标签:

【中文标题】rails api,react前端,axios,开发中的CORS不起作用【英文标题】:rails api, react front end, axios, CORS in development not working 【发布时间】:2018-06-21 11:39:56 【问题描述】:

我确定这个问题(或非常相似的问题)已经被问过很多次了,但我是跨域请求的新手,在搜索其他人的答案时,我无法发送基本请求从 React 前端到仅使用 rails-api 的后端,而两者都在开发服务器上本地运行。

任何解决此问题的帮助/帮助我理解为什么它不起作用将不胜感激!

前端:(如 onClick 函数处理程序,在端口 3000 上的 npm 开发服务器上运行)

function sendGetRequest() 
    Axios.request(
        url: 'http://localhost:3001/users/2',
        method: 'get',
        headers: 
            'Content-Type': 'application/json',
            'Accept': 'application/json'
        ,
        withCredentials: true
    ).then(function (response) 
        console.log(response);
    )
    .catch(function (error) 
        console.log(error);
    );

后端(rails rack-cors,在 rails puma 服务器上运行,端口 3001):

config.middleware.insert_before 0, Rack::Cors do
      allow do
        origins 'localhost:3000'
        resource '*',
          :headers => :any,
          :expose  => ['access-token', 'expiry', 'token-type', 'uid', 'client'],
          :methods => [:get, :post, :put, :patch, :delete, :options, :head]
      end
    end

我已经通过 postman 和 rspec 验证了各种控制器方法都正确地响应了 JSON。

当我尝试运行它时,我收到如下错误:

"加载http://localhost:3001/users/2失败:当请求的凭据模式为'include'时,响应中的'Access-Control-Allow-Origin'标头的值不能是通配符'*'。来源'@987654322 @' 因此不允许访问。由 XMLHttpRequest 发起的请求的凭据模式由 withCredentials 属性控制。"

非常感谢!

【问题讨论】:

您的origins 'localhost:3000' 行需要改为origins 'http://localhost:3000'(必须包含http:// 协议部分)。但是,即使您进行了更改,我也不认为它会解决导致问题中出现错误消息的问题。其原因似乎是http://localhost:3001 服务器的服务器代码的其他部分已经发回了Access-Control-Allow-Origin: * 响应标头。服务器应该发回一个 Access-Control-Allow-Origin: http://localhost:3001 响应头。 @sideshowbarker 明白了 - 你是对的,添加 http 协议并不能解决问题。您知道将 Access-Control-Allow-Origin 标头发送到哪里的 rails api(大概在 rack cors gem 的某个地方)吗? @sideshowbarker 我不太确定localhost 是否需要协议前缀。我有一个类似的设置,在没有“http://”的情况下可以正常工作。 @w_hile 浏览器肯定需要。 Access-Control-Allow-Origin: localhost:3001 响应标头与浏览器期望的 http://localhost:3001 源不匹配。该标头值需要是一个来源,它必须包含协议。 虽然 Origin 请求头和 ACAO 响应头的值确实需要包含该方案,但 rack-cors 中的 origins 节点通常与 Origin 头进行比较,以检查是否应发送 CORS 响应标头。所以在这种情况下,您确实可以指定origins localhost:3001 - 这将允许来自http://localhost:3001https://localhost:3001 的请求 【参考方案1】:

让我使用rack-cors 与您分享我的应用程序中的一些代码。

这是config/initializers/cors.rb中的代码。

if Rails.application.config.x.cors_allowed_origins
  Rails.application.config.middleware.insert_before 0, Rack::Cors do
    allow do
      origins Rails.application.config.x.cors_allowed_origins

      resource '*',
        headers: :any,
        methods: [:get, :post, :put, :patch, :delete, :options, :head],
        credentials: true
    end
  end
end

上面的Rails.application.config.x.cors_allowed_origins 通过环境变量设置在config/application.rb 中,以便在开发和生产中设置不同的允许来源。

config.x.cors_allowed_origins = ENV['CORS_ALLOWED_ORIGINS']

通过这些设置,该应用程序预计将使用一个环境变量启动,该环境变量接受 SPA 的运行端口,例如CORS_ALLOWED_ORIGINS=localhost:8080 bundle exec rails slocalhost:8080 这里是运行 SPA 的主机。

在 SPA 方面,这是给 whatwg-fetch 的选项。抱歉,我在这里没有使用 Axios,但它会对您有所帮助。

const options = 
  headers: 
    'Content-Type': 'application/json',
    'Accept': 'application/json'
  ,
  mode: 'cors',
  credentials: 'include'
;

【讨论】:

以上是关于rails api,react前端,axios,开发中的CORS不起作用的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的 axios 使用 React.useEffect 一遍又一遍地从 Rails 后端获取调用?

使用 React 时,rails api-only 应用程序中出现 401 未经授权的错误

我应该在后端(Rails API)还是前端(React/Redux)上查询和过滤

CORS 与 React、Webpack 和 Axios

Laravel - React,强制 Axios 进行拒绝/捕获

如何从 Heroku 中托管的 Rails API 应用程序在浏览器中设置 cookie,该应用程序在 Netlify 中托管的 React 应用程序中运行前端?