本节主要总结 Axios
提供的一些特殊功能点。
9-1.上传、下载进度
现代浏览器端通信有 XMLHttpRequest
和 fetch
两种方式。
关于这俩者较为详细的介绍,可以参考XHR/FETCH。
截止到目前,XMLHttpRequest
提供了 xhr.upload
和 xhr.onprogress
来监听上传和下载进度。
而 fetch
这方面则欠缺一些,并没有提供原生的上传和下载监听 API
。
我们已经知道 Axios
在 browser
端使用的就是 XMLHttpRequest
。
可想而知,Axios
对于上传和下载进度的监听,内部实现依赖的是 XMLHttpRequest
。
本章节,重点说明下 Axios
相应 API
的使用方式。
在 config
中,Axios
提供了两个属性 onUploadProgress
和 onDownloadProgress
:
const config = {
onUploadProgress: function (event) {
console.log(event)
},
onDownloadProgress: function (event) {
console.log(event)
}
}
9-2.取消请求
XMLHttpRequest
中提供了 xhr.abort() 来直接中止请求。
而 fetch
则是使用 AbortController 来中止请求。
那么 Axios
最开始是手动封装了 CancelToken
方法,内部主要实现依旧是将 xhr.abort()
进行 Promise
化包装。
当出现了原生方法 AbortController
之后,Axios
为了面向未来,内部兼容了 AbortController
,而且更加推荐使用 AbortController
。
CancelToken
在较高版本中的 Axios
已经逐渐被废弃。
9-2-1.CancelToken
笔者认为,CancelToken
是基于 xhr.abort()
方法封装的中止 Promise
方法的 API
。
还有一个关于 CancelToken
的设计提案cancelable promises proposal。
Axios
中的基本使用方式如下:
const { CancelToken } = axios
const source = CancelToken.source()
axios({
url: '/api',
params: {
id: '9527'
},
cancelToken: source.token
}).then(res => {
console.log(res)
}).catch(err => {
console.error(err)
})
source.cancel()
打印 source
属性如下:
9-2-2.AbortController
关于 AbortController
的详细信息,可以参考 AbortController。
本节主要总结下 AbortController
的使用方式和注意事项。
const abortController = new AbortController()
const { signal } = abortController
axios({
url: '/api',
params: {
id: '9527'
},
signal
}).then(res => {
console.log(res)
}).catch(err => {
console.error(err)
})
abortController.abort()
abortController.signal
属性打印如下:
9-3.XSRF防范
关于 XSRF
的基本机制,是利用了访问某站时,该站对应的 cookie
会被浏览器自动携带。
而攻击者则可以利用伪造页面,诱导用户点击,请求携带用户本机已经种好的 cookie
,进而触发不安全交易。
关于 XSRF
的更多详细内容,可以参考XSRF攻击及防范。
而在 Axios
中,防范 XSRF
的手段,一般可以称作双重 Cookie
防御。
具体交互逻辑如下:
- 服务端利用一些加密方式生成
Token
,然后通过Set-Cookie
返回给客户端,然后客户端在发起交易时,读取对应Cookie
,并设置到请求头headers
中,假设我们将其命名为Cookie Token
。 - 发起交易时,实际请求会发送本地
Cookie
,还会发送在请求头中设置的Cookie Token
。 - 也就是说,服务端在做交易验证时,不单单要验证请求头中的
Cookie
字段,还要验证Cookie Token
字段。
在 Axios
中,config
属性中提供了两个字段:xsrfCookieName
和 xsrfHeaderName
。
下面代码是 Axios
对于 xsrfCookieName
和 xsrfHeaderName
的处理逻辑:
if (platform.isStandardBrowserEnv) {
// Add xsrf header
const xsrfValue = (config.withCredentials || isURLSameOrigin(fullPath))
&& config.xsrfCookieName && cookies.read(config.xsrfCookieName);
if (xsrfValue) {
requestHeaders.set(config.xsrfHeaderName, xsrfValue);
}
}
可以看出,Axios
是将本地与 xsrfCookieName
对应的 Cookie
取出,然后按照 xsrfHeaderName
设置到请求头上。
该实现与我们所分析的双重 Cookie
防御逻辑是一致的。