获取 API、自定义请求标头、CORS 和跨域重定向
Posted
技术标签:
【中文标题】获取 API、自定义请求标头、CORS 和跨域重定向【英文标题】:Fetch API, custom request headers, CORS, and cross-origin redirects 【发布时间】:2017-03-27 15:04:24 【问题描述】:我需要在浏览器中使用自定义请求标头发出 HTTP GET 请求,并在结果流入时对其进行处理。Fetch API 非常适合:
fetch('https://example.com/resource',
method: 'GET',
headers:
'X-Brad-Test': 'true'
,
cache: 'no-store',
mode: 'cors'
).then((res) =>
const reader = res.body.getReader();
// etc.
);
这很好用。由于存在自定义标头,因此浏览器会使用 OPTIONS 请求将请求预先发送到/resource
。我已将服务器配置为使用 204 No Content
和以下标头进行响应:
Access-Control-Allow-Headers: X-Requested-With, Range, If-Range, X-Brad-Test
Access-Control-Allow-Origin: *
浏览器对此感到满意,然后发出 GET 请求,服务器返回带有数据的 200 OK
,浏览器允许我访问响应标头和正文。
当有重定向时问题就来了。 OPTIONS
请求成功,204 No Content
和与以前相同的标头。浏览器发出正确的GET
请求,然后在服务器上发送带有Location:
标头的302
。 Chrome 抛出以下错误:
Fetch API 无法加载 https://example.com/resource。从“https://example.com/resource”重定向到“http://some-other-origin/resource”已被 CORS 政策阻止:请求需要预检,不允许进行跨域重定向。
这出乎意料,对我来说似乎很荒谬。我希望浏览器遵循重定向,并为这个新位置发出另一个飞行前请求,但它没有这样做。
更奇怪的是我可以绕过这个客户端。我可以在没有自定义标头的情况下发出 HTTP 请求,通过查看 Response 对象找出重定向后的最终目标,然后使用我的自定义标头在新目标处发出第二个请求。当然,这并非在所有情况下都有效,我宁愿不依赖这个 hack。我宁愿找到合适的方法。
两个问题:
允许客户端遵循重定向的正确方法是什么?我可以使用某种Access-Control-*
标头吗?
为什么存在这个限制?不关注并在关注的 URL 上运行 pre-flight 可以防止哪些安全问题?
【问题讨论】:
您的 302 响应包含Access-Control-Allow-Origin: *
标头?
好的,我隐约记得过去对此的讨论,并会花一些时间回顾规范并与编辑和实施者交谈,看看我是否可以让某人在这里发布答案(或将发布一个如果我能设法先自己弄清楚,我自己)。
另见***.com/questions/34949492/…和github.com/whatwg/fetch/issues/204
另见***.com/questions/28917489/… 这个问题实际上在很久以前(3 年以上)就被发现了。
【参考方案1】:
支持重定向到需要预检的请求是对 Fetch(定义 CORS)的最新更改。
https://github.com/whatwg/fetch/commit/0d9a4db8bc02251cc9e391543bb3c1322fb882f2
我相信一些实施已经开始调整他们的实施,但这需要一些时间才能接触到每个人。
【讨论】:
谢谢。您首先知道此限制背后的原因吗?它只是一个错误还是一个极端情况?另外,有没有比我在问题中提出的更好的解决方法? 当时我们不想弄清楚处理模型,没有意识到阻止重定向实际上更复杂。这是一个错误,需要很长时间才能纠正,因为没有人真正抱怨它。 (想不出更好的解决方法。) 这方面有什么新进展吗? 我认为不多,需要有人开始编写测试并再次戳浏览器。它在我的清单上,但遗憾的是,它的清单很长。 @Anne 2018 年的问候!有没有偶然更新?谢谢。以上是关于获取 API、自定义请求标头、CORS 和跨域重定向的主要内容,如果未能解决你的问题,请参考以下文章
IE9 重定向缓存、字体和跨域资源共享 (CORS) CDN HTTP 标头
带有自定义标头的 Ajax 请求发送到启用 CORS 的 Web API 服务器