一比一还原axios源码(八)—— 其他功能
到此,我们完成了axios的绝大部分的功能,接下来我们来补全一下其他的小功能。
一、withCredentials
这个参数可以可以表明是否是一个跨域的请求。那这个的使用场景是啥呢?就是我们在同域的请求的情况下,是会默认携带cookie的,跨域的话就不会携带cookie,如果我们想要跨域请求并携带cookie,那么就需要这个参数了。当然这个实现非常简单:
if (!utils.isUndefined(config.withCredentials)) {
request.withCredentials = !!config.withCredentials;
}
嗯,就这样就完了。
然后我们需要创建一个作为接受跨域请求的server2.js作为跨域访问的服务器。代码可以在gitHub上看哦。就不多说了。
二、XSRF 防御
就是跨站请求伪造,登录信任的A网站后会产生该用户的信任cookie,由于浏览器在发送请求的时候会自动携带cookie,如果用户在没有登出的情况下登录黑客网站,那么就会把带有信任的cookie传递给黑客网站,此时黑客网站拿到你的用户cookie就可以伪造用户登录A网站了。
XSRF的防御手段有很多,比如referer,但是referer也是可以伪造的,所以杜绝此类攻击的一种方式是服务器端要求每次请求都包含一个token
,这个token
不在前端生成,而是在我们每次访问站点的时候生成,并通过set-cookie
的方式种到客户端,然后客户端发送请求的时候,从cookie
中对应的字段读取出token
,然后添加到请求headers
中。这样服务端就可以从请求headers
中读取这个token
并验证,由于这个token
是很难伪造的,所以就能区分这个请求是否是用户正常发起的。
所以在axios中,我们需要自动把这些事情做了,每次发送请求的时候,从cookie
中读取对应的token
值,然后添加到请求headers
中。我们允许用户配置xsrfCookieName
和xsrfHeaderName
,其中xsrfCookieName
表示存储token
的cookie
名称,xsrfHeaderName
表示请求headers
中token
对应的header
名称。
例子就像这样:
const instance = axios.create({
xsrfCookieName: 'XSRF-TOKEN-D',
xsrfHeaderName: 'X-XSRF-TOKEN-D'
}) instance.get('/more/get').then(res => {
console.log(res)
})
那么接下来我们来看下代码的实现:
首先,我们在defaults中添加两个默认参数:
var defaults = {
// ...
xsrfCookieName: "XSRF-TOKEN",
xsrfHeaderName: "X-XSRF-TOKEN",
// ... }
首先啊,我们要做一些判断,首先要判断如果是配置 withCredentials
为 true
或者是同域请求,我们才会请求 headers
添加 xsrf
相关的字段,然后我们在helpers文件夹下创建一个isURLSameOrigin文件,用来判断是否是同源,我直接从axios复制过来的,哈哈。代码大家自己去看注释哦。它的核心其实就是创建个a标签,然后设置属性为我们传入的url地址,通过这个DOM,我们就可以获取到对应url的protocol、host等属性,然后我们判断这两个是否相同就可以了。
然后,我们在创建个cookies文件,也是在helpers文件夹中,这个cookies主要封装了一些cookie的读写操作。
最后,就是我们的核心逻辑代码了,其实很简单:
if (utils.isStandardBrowserEnv()) {
// Add xsrf header
var xsrfValue =
(config.withCredentials || isURLSameOrigin(config.url)) &&
config.xsrfCookieName
? cookies.read(config.xsrfCookieName)
: undefined;
if (xsrfValue) {
requestHeaders[config.xsrfHeaderName] = xsrfValue;
}
}
首先判断是否是浏览器环境,如果是的话,就再判断是否有withCredentials或者是同源的,并且有xsrfCookieName,然后读取cookie中的xsrfCookieName的值,然后设置给headers即可。其实核心逻辑并不复杂,复杂的是XSRF的概念,和一些它的判断条件中的方法。
最后,在我们的demo里,我们还要设置下server.js:
app.use(express.static(__dirname, {
setHeaders (res) {
res.cookie('XSRF-TOKEN-D', '1234abc')
}
}))
这样才可以。
三、上传下载进度监控
其实上传和下载的进度监控,都可以通过xhr的原生的对象来进行获取。这是axios的文档:
我们先来看实现吧,实现起来非常简单,其实就是传了个参数,xhr里调用一下:
// Handle progress if needed
if (typeof config.onDownloadProgress === 'function') {
request.addEventListener('progress', config.onDownloadProgress);
} // Not all browsers support upload events
if (typeof config.onUploadProgress === 'function' && request.upload) {
request.upload.addEventListener('progress', config.onUploadProgress);
}
就这么简单,完事了。。。。demo的话我就不在这里占篇幅了,大家去项目里看下。
四、Authorization
HTTP 协议中的 Authorization 请求 header 会包含服务器用于验证用户代理身份的凭证,通常会在服务器返回 401 Unauthorized 状态码以及 WWW-Authenticate 消息头之后在后续请求中发送此消息头。
axios 库也允许你在请求配置中配置 auth
属性,auth
是一个对象结构,包含 username
和 password
2 个属性。一旦用户在请求的时候配置这俩属性,我们就会自动往 HTTP 的 请求 header 中添加 Authorization
属性,它的值为 Basic 加密串
。 这里的加密串是 username:password
base64 加密后的结果。
axios文档中是这样说明的:
我们来看下代码实现:
// HTTP basic authentication
if (config.auth) {
var username = config.auth.username || "";
var password = config.auth.password
? unescape(encodeURIComponent(config.auth.password))
: "";
requestHeaders.Authorization = "Basic " + btoa(username + ":" + password);
}
就这么简单~~。
五、自定义合法状态码
额。。。跟文档一模一样。。。。那我们在判断promise是走resolve还是reject的时候,就要额外的处理下了,对了,大家还记得我们实在哪里执行的了不?还记不记得有个settle文件?
export default function settle(resolve, reject, response) {
var validateStatus = response.config.validateStatus;
if (!response.status || !validateStatus || validateStatus(response.status)) {
resolve(response);
} else {
reject(
createError(
"Request failed with status code " + response.status,
response.config,
null,
response.request,
response
)
);
}
}
嗨(四声)!就是个判断!
六、自定义参数序列化
我们先来看文档:
这个东西呢,允许我们自己定义规则解析url后的query参数,大多数情况下用不到吼。
七、baseURL
有些时候,我们会请求某个域名下的多个接口,我们不希望每次发送请求都填写完整的 url,希望可以配置一个 baseURL
,之后都可以传相对路径。我们一旦配置了 baseURL
,之后请求传入的 url
都会和我们的 baseURL
拼接成完整的绝对地址,除非请求传入的 url
已经是绝对地址。
var fullPath = buildFullPath(config.baseURL, config.url);
request.open(
config.method.toUpperCase(),
buildURL(fullPath, config.params, config.paramsSerializer),
true
);
八、静态方法扩展
额。。。直接看代码吧,懒得说了~~~
首先,扩展几个静态方法:
// Expose all/spread
axios.all = function all(promises) {
return Promise.all(promises);
};
axios.spread = function spread(callback) {
return function wrap(arr) {
return callback.apply(null, arr);
};
}; // Expose isAxiosError
axios.isAxiosError = function isAxiosError(payload) {
return utils.isObject(payload) && payload.isAxiosError === true;
};
然后,扩展个getUri方法:
Axios.prototype.getUri = function getUri(config) {
config = mergeConfig(this.defaults, config);
return buildURL(config.url, config.params, config.paramsSerializer).replace(
/^\?/,
""
);
};
撒花,完结~
一比一还原axios源码(八)—— 其他功能的更多相关文章
- 一比一还原axios源码(零)—— 概要
从vue2版本开始,vue-resource就不再被vue所维护和支持,官方也推荐使用axios,所以,从我使用axios至今,差不多有四五年了,这四五年的时间只能算是熟练应用,很多内部的实现和原理不 ...
- 一比一还原axios源码(四)—— Axios类
axios源码的分析,到目前为止,算上第0章已经四章了,但是实际上,还都没有进入axios真正的主线,我们来简单回顾下.最开始我们构建了get请求,写了重要的buildURL方法,然后我们处理请求体请 ...
- 一比一还原axios源码(一)—— 发起第一个请求
上一篇文章,我们简单介绍了XMLHttpRequest及其他可以发起AJAX请求的API,那部分大家有兴趣可以自己去扩展学习.另外,简单介绍了怎么去读以及我会怎么写这个系列的文章,那么下面就开始真正的 ...
- 一比一还原axios源码(三)—— 错误处理
前面的章节我们已经可以正确的处理正确的请求,并且通过处理header.body,以及加入了promise,让我们的代码更像axios了.这一章我们一起来处理ajax请求中的错误. 一.错误处理 首先我 ...
- 一比一还原axios源码(六)—— 配置化
上一章我们完成了拦截器的代码实现,这一章我们来看看配置化是如何实现的.首先,按照惯例我们来看看axios的文档是怎么说的: 首先我们可以可以通过axios上的defaults属性来配置api. 我们可 ...
- 一比一还原axios源码(二)—— 请求响应处理
上一章,我们开发了一些简单的代码,这部分代码最最核心的一个方法就是buildURL,应对了把对象处理成query参数的方方面面.虽然我们现在可以发起简单的请求了,但是第一,我们无法接收到服务器的响应, ...
- 一比一还原axios源码(五)—— 拦截器
上一篇,我们扩展了Axios,构建了一个Axios类,然后通过这个Axios工厂类,创建真正的axios实例.那么今天,我们来实现下Axios的拦截器也就是interceptors.我们来简单看下Ax ...
- Axios源码深度剖析 - 替代$.ajax,成为xhr的新霸主
前戏 在正式开始axios讲解前,让我们先想想,如何对现有的$.ajax进行简单的封装,就可以直接使用原声Promise了? let axios = function(config){ return ...
- Axios源码分析
Axios是一个基于promise的HTTP库,可以用在浏览器和node.js中. 文档地址:https://github.com/axios/axios axios理解和使用 1.请求配置 { // ...
随机推荐
- scons: 使用 SCons 轻松建造程序
转载请注明来源:https://www.cnblogs.com/hookjc/ 在软件项目开发过程中,make 工具通常被用来建造程序.make 工具通过一个被称为 Makefile 的配置文件可以自 ...
- C++中的常见错误
1.变量定义位置错误 1 int sum = 0; 2 3 do 4 { 5 int i = 1; 6 sum += i; 7 i++; 8 }while(i <= 100);//错误:i没有定 ...
- 索引,事务,存储引擎和选择,视图,mysql管理
一.mysql索引:提高数据库的性能(不用加内存,不用改程序,不用调sql,查询速度就可能提高百倍千倍)索引会占用磁盘空间 CREATE INDEX 索引名 ON 数据表 (列名or字 ...
- Springboot+Websocket+JWT实现的即时通讯模块
场景 目前做了一个接口:邀请用户成为某课程的管理员,于是我感觉有能在用户被邀请之后能有个立马通知他本人的机(类似微博.朋友圈被点赞后就有立马能收到通知一样),于是就闲来没事搞了一套. 涉及技术栈 ...
- 03并发编程(多道技术+进程理论+进程join方法)
目录 03 并发编程 03 并发编程
- IDEA 2021 没有Allow parallel run
IDEA 2021 没有Allow parallel run 尝试运行多个客户端. 新版IDEA找不到Allow parallel run
- 防世界之Web_ics-06
题目: 进入实验环境,发现其他页面啥都没有,题目描述说报表中心数据被删,打开报表中心看看 进入数据中发现url上有?id=1的字样就要注意,敏感起来.id是数值,可以尝试爆破一下. 打开burpsui ...
- Jenkins+allure集成报告构建
1.点击新建item,新建一个job 对这个job进行配置 General模块,点击高级 勾选自定义的工作空间,填写项目目录 构建触发器和构建环境先不填写 构建模块,填写python main.py, ...
- IP网络主动测评系统——IT运维人员的好帮手
一.前 言 随着计算机网络的普及和快速发展,互联网已经融入到人们的衣食住行等方方面 面,如工作.购物.音视频聊天.视频会议.朋友圈.抖音.在线网游.网络电影 电视等.毫不夸张地说,现如今大部分人的绝大 ...
- 软考高级及杭州E类人才申请经验分享
目录 前沿 软考高项 什么是软考 软考的基本过程 报名 是否报班 高项考些什么以及需要哪些书 如何准备 杭州E类人才申请 如何申请 大概的流程 前沿 挺久没更新了,自从成为房奴后,看书的时间就变少了, ...