Apollo graphQL 客户端中的 CORS 异常“预检响应中的 Access-Control-Allow-Headers 不允许请求标头字段内容类型”

问题描述

我正在开发一个客户端呈现的 React Web 应用程序,它具有明确分离的后端/前端结构。后端是一个典型的graphQL服务器,前端使用一个Apollo graphQL客户端进行查询

当应用部署给客户时,我开始观察到 HTTP 请求失败的增加错误消息如下所示。

在 Chrome 中,Failed to fetch

在 Firefox 中,NetworkError when attempting to fetch resource.

在 Safari 中,Request header field Content-Type is not allowed by Access-Control-Allow-Headers.

检查收集到的客户端错误日志后,我发现这些发生在相当旧的浏览器版本上,例如Chrome 49 ~ 58、Firefox 57 和 Safari 10 ~ 11。

该问题似乎与 CORS 相关,而较旧的浏览器似乎有不同的行为。我尝试通过 browserslist 将浏览器支持扩展到此类范围,但这没有帮助。

我看到了像 this 这样的帖子,这些帖子都在谈论将 content-type 添加到服务器响应中的 Access-Control-Allow-Headers 标头,但我认为我的情况有点不同,因为这只发生在较旧的浏览器版本。如果我的后端没有为 CORS 正确运行,则会影响所有请求。

解决方法

我设法确定了罪魁祸首是 Apollo graphQL 客户端在幕后使用的 fetch API。

当我尝试在旧浏览器版本中重现该问题时,在控制台上观察到以下错误消息。

Fetch API cannot load https://account.xxx.com/ap/sso?openid.pape.max_auth_age=3600&signIn...
Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response.

显然请求被重定向以进行 SSO 登录。这让我怀疑 API 在发送请求时无法正确附加 cookie,因此没有提供身份验证令牌。

这在 Fetch API doc 上得到确认,它仅在 2017 年 8 月将其默认凭据政策更改为 same-origin。因此,除非另有说明,否则在此之前发布的所有浏览器都不会包含 Cookie。

我遵循了 Apollo 客户端的 advanced HTTP networking 文档并在下面包含了 fetch 选项,它开始像魅力一样工作。

{ credentials: 'same-origin' }

旁注是,如果策略设置为 include,则在 Access-Control-Allow-Origin 标头无法设置为通配符匹配 {{1} } 在 HTTP 响应中。

在这种情况下,错误消息将如下所示。

*