CORS异常“预检响应中的Access-Control-Allow-Headers不允许请求头字段内容类型"在 Apollo graphQL 客户端中 [英] CORS exception "Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response" in Apollo graphQL client

查看:308
本文介绍了CORS异常“预检响应中的Access-Control-Allow-Headers不允许请求头字段内容类型"在 Apollo graphQL 客户端中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am developing a client side rendered React web application that has a clearly segregated backend/frontend structure. The backend is a typical graphQL server, and an Apollo graphQL client in the frontend is used to make queries.

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

When the app was deployed to customers, I started observing an increase in HTTP request failures. The error messages look like below.

在 Chrome 中,获取失败.

In Chrome, Failed to fetch.

在 Firefox 中,尝试获取资源时出现网络错误..

In Firefox, NetworkError when attempting to fetch resource..

在 Safari 中,请求头字段 Content-Type 不被 Access-Control-Allow-Headers 允许..

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

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

Upon inspection on the client side error logs collected, I found that these occurred on pretty old browser versions, e.g. Chrome 49 ~ 58, Firefox 57 and Safari 10 ~ 11.

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

The issue seems related to CORS and the older browsers seem to have a different behaviour. I tried to extend browser support to such ranges via browserslist but that didn't help.

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

I landed on posts like this which all talk about adding content-type to the Access-Control-Allow-Headers header in the server's response, but I think my situation is a bit different as this only occurs on older browser versions. If my backend were not acting correctly for CORS, it would affect all requests.

推荐答案

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

I managed to identify the culprit to be the fetch API used behind the scene by the Apollo graphQL client.

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

When I tried to reproduce the issue in older browser versions, below error message was observed on the console.

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,因此没有提供身份验证令牌.

Apparently the request is being redirected for SSO login. That led to me to suspect that the API was not able to attach the cookies properly when sending in the request, hence no auth token was provided.

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

This is confirmed on the Fetch API doc that it only changed its default credential policy to same-origin in August 2017. Hence all browsers released before that won't include cookies unless specified otherwise.

我遵循了高级 HTTP 网络 docApollo 客户端并包含在 fetch 选项下面,它开始像魅力一样工作.

I followed the advanced HTTP networking doc of the Apollo client and included below fetch option, and it started working like a charm.

{ 凭证:'同源'}

旁注是,如果策略设置为 include,则在 Access-Control-Allow-Origin 标头不能设置为 HTTP 响应中的通配符匹配 *.

A side note is that if the policy is set to include, it poses a stricter limit on the backend server in CORS situations where the Access-Control-Allow-Origin header cannot be set to wildcard match * in the HTTP response.

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

The error message would look like below in such situation.

从源 'http://0.0.0.0:4321' 获取在 'http://127.0.0.1:1234/graphql' 的访问已被 CORS 策略阻止:对预检请求的响应没有通过访问控制检查:当请求的凭据模式为包含"时,响应中Access-Control-Allow-Origin"标头的值不得为通配符*".

这篇关于CORS异常“预检响应中的Access-Control-Allow-Headers不允许请求头字段内容类型"在 Apollo graphQL 客户端中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆