为啥 Rails 无法识别请求标头中的 `Accept: application/json`?

Posted

技术标签:

【中文标题】为啥 Rails 无法识别请求标头中的 `Accept: application/json`?【英文标题】:Why does rails not recognize `Accept: application/json` in the request header?为什么 Rails 无法识别请求标头中的 `Accept: application/json`? 【发布时间】:2020-01-21 02:34:03 【问题描述】:

我有一些前端 javascript 向我的后端 rails 服务器发出异步 http 请求。在前端,我 使用 XHR(我使用 axios,尽管这与问题并不完全相关)。

在请求中,我设置了以下内容来告诉服务器我正在发送 JSON 并确保我返回 JSON:

const config = 
  headers: 
    "Content-Type": "application/json",
    "Accept": "application/json"
  
;

在我的后端 Rails 控制器中,如果检查请求,我可以验证 Accept 标头:

> request.headers
"HTTP_ACCEPT"=>"application/json, text/plain, */*"

但是 ActionPack/Rails 仍然不尊重这一点,默认为 format:html

> request.format
=> #<Mime::Type:0x00007fe223919f80 @hash=-1773238723920954657, @string="text/html", @symbol=:html, @synonyms=["application/xhtml+xml"]>

为什么会这样?

我知道我可以将 .json 附加到我的请求 URL 以“强制”它指定该格式,但这是唯一的选择吗?我可以很容易地附加它,但它似乎是特定于 Rails 的实现,而不是真正的“正确”方法。

此外,source code for the request.format method 明确将:json 设置为 XHR 请求的格式 - Rails 目前是否只尊重 XHR 请求?

谢谢!

【问题讨论】:

【参考方案1】:

您所做的是正确的,但是从浏览器发送 Axios/Fetch API 请求会从浏览器端显示“CORS”错误(您可以在浏览器开发工具控制台中看到它)。您可以通过MDN Docs了解更多信息

要解决此问题,您需要将Access-Control-Allow-Origin 标头发送到您在网络服务器上收到的请求。您可以通过在application_controller.rb 中添加此标头来手动执行此操作,或者只需使用像rack-cors 这样的gem。我将向您展示如何使用rack-cors gem:

在您的Gemfile 中添加gem 'rack-cors' 运行命令bundle i

在您的 config/application.rb 文件中,添加以下行:

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

现在重新启动您的 Rails 服务器

您还可以查看以上说明和更多详细信息here

现在再次进行 API 调用,不要在 URL 末尾强制使用 .json,它应该可以工作。

【讨论】:

我最近发现了一篇关于 CORS 的好文章 - dev.to/miguelmota/… 感谢您的解释!但我的请求不是跨域的。我的前端和后端在同一个域下。 你能更新你的axios请求的代码吗?您在控制台中看到任何错误吗? rails server 日志中有任何具体内容吗? 我刚刚在一个测试应用程序中进行了测试 - react + rails(一个应用程序),我使用了 Fetch API,它工作正常。

以上是关于为啥 Rails 无法识别请求标头中的 `Accept: application/json`?的主要内容,如果未能解决你的问题,请参考以下文章

无法从获取请求中获取“Access-Control-Allow-Origin”标头

来自 IE 或 Firefox 的 CORS 请求中没有 Referer 标头

为啥 JWT 需要作为 Bearer Token 标头发送?

即使设置了标头,也无法验证 CSRF 令牌的真实性 Rails 4 Ajax

在启用 CORS 的情况下,无法从我的请求标头中检索我的 x-api-key。为啥?

如何让不记名令牌通过rails中的标头传递?