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

Posted

技术标签:

【中文标题】Apollo graphQL 客户端中的 CORS 异常“Access-Control-Allow-Headers 在预检响应中不允许请求标头字段内容类型”【英文标题】:CORS exception "Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response" in Apollo graphQL client 【发布时间】:2021-04-21 02:16:19 【问题描述】:

我正在开发一个客户端渲染的 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,则会影响所有请求。

【问题讨论】:

【参考方案1】:

我设法确定罪魁祸首是 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,则在 HTTP 响应中无法将 Access-Control-Allow-Origin 标头设置为通配符匹配 * 的 CORS 情况下,它会对后端服务器造成更严格的限制。

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

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’.

【讨论】:

我认为这里很好的学习是,当在 Web 应用程序中引入任何新东西时,浏览器支持是一个检查点,尽管这样做可能会很麻烦和讨厌。

以上是关于Apollo graphQL 客户端中的 CORS 异常“Access-Control-Allow-Headers 在预检响应中不允许请求标头字段内容类型”的主要内容,如果未能解决你的问题,请参考以下文章

GraphQL:无法读取 Apollo 客户端中的响应标头

使用 Apollo 客户端根据 React 组件中的节点类型值发出条件 GraphQL 请求

使用 graphql 和 apollo 客户端刷新 Angular 令牌

使用 Laravel Lighthouse 在 Laravel 7 中出现 CORS 错误

对象作为突变中的输入变量:GraphQL - Apollo - React

在客户端解析器中导入类型时,如何避免使用 Apollo 客户端和“graphql-codegen”的角度项目中的循环依赖?