Fetch API 默认跨域行为

Posted

技术标签:

【中文标题】Fetch API 默认跨域行为【英文标题】:Fetch API default cross-origin behavior 【发布时间】:2017-10-22 15:18:21 【问题描述】:

Fetch Specifications 说默认的 Fetch 模式是 'no-cors' -

请求具有关联的模式,即“same-origin”、“cors”、“no-cors”、“navigate”或“websocket”。除非另有说明,否则它是“no-cors”。

但是,我似乎注意到mode: 'no-cors' 和未指定模式之间的这种行为差异。正如JSFiddle sample 中所展示的,将模式显式定义为“no-cors”会使 javascript 无法访问响应,而未指定模式会使调用方法可以使用 Response 对象。

明确指定获取模式的工作方式是否与内部使用相同模式的默认行为不同?我在这里错过了什么?

【问题讨论】:

【参考方案1】:

对于跨域请求,Fetch 算法将请求的“response tainting” 设置为cors,并要求使用CORS protocol 执行提取。

具体看“Main fetch” algorithm第12步的以下子步骤:

request 的当前 url 的来源与 request 的来源相同 原点和 CORS 标志未设置请求当前url的scheme是“data请求的模式是“navigate”或“websocket 1. 设置请求响应污染为“basic”。 2. 返回使用 request 执行方案获取的结果。 … ↪ 请求的模式是“no-cors 1. 将 request 的响应污染设置为“opaque”。 2. 返回使用 request 执行方案获取的结果。 … ↪ 否则 1. 设置请求响应污染为“cors”。 2. 使用设置了CORS标志的请求返回执行HTTP fetch的结果。

它的意思是,如果请求 URL 与您的代码的来源不同,并且方案不是 data 并且模式不是 navigatewebsocket 或不是明确设置为no-cors,然后达到Otherwise条件,并使用CORS protocol发出请求。

这种解释稍微简化了一些事情,因为在请求具有触发浏览器进行预检的特征的情况下,有一个子步骤就在否则子步骤的上方,但会再次到达在这种情况下,“响应污染”被设置为cors

但是,我似乎注意到mode: 'no-cors' 和未指定模式之间的这种行为差异。

不同之处在于,当您为请求显式设置 mode: 'no-cors' 时,在这种情况下,“↪ 请求的模式是“no-cors”” 子步骤会到达,而不是 否则 子步骤。

(虽然我认为也许可以改进规范以更清楚地说明此时的模式实际上并不只是默认为no-cors——这可能是您根据 “除非另有说明,它是问题中引用的规范中的“no-cors声明。)

正如这个 JSFiddle 示例中所展示的,将模式显式定义为“no-cors”会使 Javascript 无法访问响应,

是的——那是因为它导致 “↪ request's mode is "no-cors"” 子步骤在“Main fetch”算法中到达,而不是 Otherwise子步骤。

如果不指定模式,则 Response 对象可用于调用方法。

因为 Otherwise 子步骤确实会到达,所以会执行支持 CORS 的提取。

显式指定获取模式的工作方式与内部使用相同模式的默认行为不同吗?

是的,对于跨域请求,显式设置 mode: 'no-cors' 会强制在不使用 CORS 的情况下发出请求,而未指定会导致使用 CORS 发出请求。

但如上所述,我认为也许应该完善规范以使其更加清晰。

我认为 “除非另有说明,否则它是“no-cors”” 关于模式的声明绝对不是要指定使用 fetch(…) 方法发出的请求没有指定的显式模式最终将其模式锁定为no-cors

【讨论】:

以上是关于Fetch API 默认跨域行为的主要内容,如果未能解决你的问题,请参考以下文章

React + fetch API + 百度地图api + 跨域 填坑

尝试从 api 获取令牌时节点获取的错误行为

fetch的使用(需要解决跨域问题)

Ajax新玩法fetch API

fetch.js是啥

javascript fetch 时 php session_start() 的奇怪行为