概括
Safari 拒绝了一些涉及重定向的 CORS 请求,声称某些 header 是不允许的。但是该 header 从未被脚本请求过,而是由浏览器添加的,所以我认为这无关紧要。
错误表明 CORS 中不允许某些 header
我正在观察 Safari 似乎比其他浏览器更严格地解释 CORS 协议(protocol)的情况。它拒绝某些带有错误消息的请求
[Error] Failed to load resource: Request header field … is not allowed by
Access-Control-Allow-Headers
.
我已经在标题字段中看到了这个
Accept-Encoding
,然后将该字段添加到 Access-Control-Allow-Headers
DNT
重复了同样的错误. Access-Control-Request-Headers
中包含的其他字段预检请求列表是 Cache-Control
, Origin
和 Accept-Language
.据我所知,这只会影响被重定向的请求。在我设法立即命名最终位置的情况下,请求成功。
WHATWG XHR:请求应该没有作者设置的 header
我创建了
XMLHttpRequest
在我自己的代码中,没有任何库或框架干扰它。我绝对确定我从来没有打过 setRequestHeader()
方法。 关注 WHATWG XHR spec因此,我假设我的 author request headers列表应该是空的。 Request部分指出:
The author request headers is an initially empty header list.
我可以在文档中读到
send()
的非空参数可能会触发 Content-Type
作为作者请求 header ,但即使使用这种无参数调用,我也遇到问题。W3C CORS:只有作者设置的标题才重要
W3C CORS recommendation描述 the
Access-Control-Request-Headers
field由作者请求 header 组成:If author request headers is not empty include an
Access-Control-Request-Headers
header with as header field value a comma-separated list of the header field names from author request headers in lexicographical order, each converted to ASCII lowercase (even when one or more are a simple header).
根据该规范,我可以看到的错误的可能原因是:
If the field name of each header in author request headers is not an ASCII case-insensitive match for one of the header field names in headers and the header is not a simple header, apply the cache and network error steps.
WHATWG Fetch 从 XHR 获取列表
也许 W3C CORS 推荐是错误的地方。也许它已被 WHATWG Fetch living standard 取代?在其关于 CORS-preflight fetch 的部分中写道
Let headers be the names of request's header list's headers, excluding CORS-safelisted request-headers and duplicates, sorted lexicographically, and byte-lowercased.
Let value be the items in headers separated from each other by 0x2C.
Set
Access-Control-Request-Headers
to value in preflight's header list.
那么这里的标题列表是什么?生活水平之间的联系XHR和 Fetch似乎是 the
send()
method specification .
Let req be a new request, initialized as follows:
因此,它将作者请求 header (根据我上面的考虑应该为空)绑定(bind)到用于构建请求 header 列表的 header 列表。至少在最初。
标题可能会被添加
当然,Fetch 规范很长,很多地方都提到了“header list”这个词。很可能在某处有一些条款要求添加某些标题字段。但我看不到
Accept-Encoding
的部分或 DNT
明确提到作为预期的补充。它们被列为 forbidden headers作者不应该控制的。但是,以下来自 HTTP-network-or-cache fetch 的文本部分在注释中提到了它们:
Modify httpRequest's header list per HTTP.
Note: It would be great if we could make this more normative somehow. At this point headers such as
Accept-Encoding
,Connection
,DNT
, andHost
, are to be appended if necessary.
Accept
,Accept-Charset
, 和Accept-Language
此时不应包括在内。
Note:
Accept
andAccept-Language
are already included (unlessfetch()
is used, which does not include the latter by default), andAccept-Charset
is a waste of bytes. See HTTP header layer division for more details.
我发现很难判断这个添加的范围。除了作者指定的那些之外,“为每个 HTTP 添加 header ”是否是 CORS 考虑额外 header 的原因?但为什么只在重定向的情况下? HTTP-redirect fetch部分没有提到向请求 header 列表添加更多 header 。
观察到的行为会很糟糕
如果我观察到的行为符合规范,那么我主要担心的是它本质上会阻止添加新的有用的 HTTP header 。您永远不会知道哪些网站可能会突然被破坏,因为浏览器不仅开始添加它们,而且还开始将它们包含在 CORS 检查中。另一方面,只考虑作者创建的脚本,将请求创建库与服务器实现相匹配就足够了,而不必担心浏览器会做什么。对我来说听起来像是一个更理智的设置。
题
所以我重复我的主要问题:- Safari 的行为是否是一个错误,
- 规范有问题吗,或者
- 有没有理由让事情变成这样?
解决方法
对于一台服务器,我刚刚通过 configuring my Apache 解决了这个问题至 return all headers ,但这更像是一种解决方法。我想真正了解 Safari 在这里做什么,以及为什么。
交叉链接
SO上有几个问题表明Safari在CORS和重定向的组合方面存在问题:- Safari Ajax cors request not following redirect (2013)
接受的答案指出“Apple 声称这是编写 HTML 规范的方式”,但没有引用来源。听起来像 Webkit bug 112471 comment 2除了那个答案早于评论。- HTML5 CORS request fails in safari after redirect (2014)
接受的自我回答提出了服务器辅助的解决方法。- Safari fails CORS request after 302 redirect (2015)
未接受的答案提到了 webkit bug 98838 (未经证实)这反过来又暗示 bug 112471 (最近修复)。那个人在某些时候还提到了 bug 63460标题为“CORS 应该只处理由脚本作者设置的请求 header ”,但似乎没有就此达成明确的共识。接近尾声DNT
标志是明确命名的。- Safari turns Simple Cors Request into Preflight after 302 redirect (2015)
未答复。
右侧的类似问题列表可能会提供更多信息。
最佳答案
如果您下次将问题分开,可能会有所帮助。
Accept
,但我想不出一个会影响 CORS 的。 所以是的,我认为 Safari 有一个错误,但他们最近一直在这方面做出改变,所以 WebKit nightlies 或 Safari Technology Preview 可能会做得更好。
关于http - 由于浏览器设置的 header ,Safari 拒绝重定向的 CORS 请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39354408/