跨源资源共享

跨源资源共享(CORS:Cross-Origin Resource Sharing)定义了浏览器与服务器如何实现跨源通信。CORS 背后的基本思路就是使用自定义的 HTTP 头部允许浏览器和服务器相互了解,以确实请求或响应应该成功还是失败

预检请求

CORS 通过预检请求(preflighted request)的服务器验证机制,允许使用自定义头部、除 GET 和 POST 之外的方法,以及不同请求体内容类型。在要发送涉及上述某种高级选项的请求时,会先向服务器发送一个“预检”请求。这个请求使用 OPTIONS 方法发送并包含以下头部:

  • Origin:发送请求的页面的源(协议、域名、端口)
  • Access-Control-Request-Method:请求希望使用的方法
  • Access-Control-Request-Headers:(可选)自定义头部列表,多个使用逗号分隔

在这个请求发送后,服务器可以确定是否允许这种类型的请求。服务器通过在响应中发送如下头部与浏览器沟通信息:

  • Access-Control-Allow-Origin:发送请求的页面的源(协议、域名、端口)
  • Access-Control-Allow-Methods:允许的方法,多个用逗号分隔
  • Access-Control-Allow-Headers:服务器允许的头部。多个用逗号分隔
  • Access-Control-Max-Age:缓存预检请求的秒数

预检请求返回后,结果会按响应指定的时间缓存一段时间。换句话说,只有第一次发送这种类型的请求时才会多发送一次额外的 HTTP 请求

凭据请求

默认情况下,跨源请求不提供凭据(cookie、HTTP 认证和客户端 SSL 证书)。可以通过将 withCredentials 属性设置为 true 来表明请求会发送凭据

如果发送了凭据请求而服务器返回的响应中没有这个头部,则浏览器不会把响应交给 JavaScript(responseText 是空字符串,status 是0,onerror() 被调用)

服务器也可以在预检请求的响应中发送这个 HTTP 头部,以表明这个源允许发送凭据请求

替代性跨源技术

图片探测

利用 <img>标签实现跨域通信

可以动态创建图片,然后通过他们的 onload 和 onerror 事件处理程序得知何时收到响应,这种技术常用于图片探测(image pings)

图片探测频繁用于跟踪用户在页面上的点击操作或动态显示广告。当然,图片探测的缺点是只能发送 GET 请求和无法获取服务器响应的内容。这也是只能利用图片探测实现浏览器与服务器单向通信的原因

JSONP

JSONP 是“JSON with padding”的简称

JSONP 调用是通过动态创建<script>元素并为 src 属性指定跨域 URL 实现的。此时的<script>与<img>元素类似,能够不受限制的从其他域加载资源。因为 JSONP 是有效的 JavaScript,所以 JSONP 响应在被加载完成后会立即执行

JSONP 的两个缺点:

  • JSONP 是从不同的域拉取可执行代码。如果域不可信,则可能在响应中加入恶意内容。此时除了完全删除 JSONP 没有其他办法
  • 不好确定 JSONP 请求是否失败

Fetch API

Fetch API 能够执行 XMLHttpRequest 对象的所有任务,但更容易使用,接口也更现代化,能够在 Web 工作线程等现代 Web 工具中使用。XMLHttpRequest 可以选择异步,而 Fetch API 则必须是异步

Fetch API 也能够应用在服务线程(service worker)中,提供拦截、重定向和修改通过 fetch() 生成的请求接口

Fetch 标准定义请求、响应,以及绑定二者的流程:获取(fetch)

基本用法

fetch() 方法暴露在全局作用域中,包括主页面执行线程、模块和工作线程

1、分派请求

fetch() 的唯一必需参数是要获取资源的 URL,该方法返回一个 Promise。URL 格式(相对路径、绝对路径)的解释与 XHR 对象一样

2、读取响应

如果要取得纯文本格式的内容,要用到 text() 方法。示例代码如下:

1
2
3
4
5
6
7
8
9
10
fetch('bar.txt').then(res => {
res.text().then(data => {
console.log(data) // bar.txt 的内容
})
})

// 或者

fetch('bar.txt').then(res => res.txt()).then(data => console.log(data))
// bar.txt 的内容

3、处理状态码和请求失败