Apollo graphQL 客户端中的 CORS 异常 "Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response"

CORS exception "Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response" in Apollo graphQL client

我正在开发客户端呈现的 React Web 应用程序,它具有明确隔离的 backend/frontend 结构。后端是一个典型的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 将浏览器支持扩展到这样的范围,但这没有帮助。

我登陆了像 这样的帖子,这些帖子都在谈论将 content-type 添加到服务器响应中的 Access-Control-Allow-Headers header,但我认为我的情况有点不同,因为这只发生在旧的浏览器版本上。如果我的后端没有为 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 文档并包含了下面的获取选项,它开始像一个魅力一样工作。

{ credentials: 'same-origin' }

附带说明一下,如果该策略设置为 include,它会在无法设置 Access-Control-Allow-Origin header 的 CORS 情况下对后端服务器施加更严格的限制HTTP 响应中的通配符匹配 *

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

Access to fetch at 'http://127.0.0.1:1234/graphql' from origin 'http://0.0.0.0:4321' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include’.