undici使用fileCookieStore来自定存储和发送Cookie

自接触node并开始使用node,request便是我一直在使用的HTTP请求工具,但是遗憾的是,该工具早在2020年2月11日便已经被标记为弃用停止维护了,request库很强大也很好用,但是对于过时的东西使用起来总归会有一些隐患,我不得不去寻找一个新的适用于node的HTTP请求工具,寻找一个能够替代的库真的挺不容易的,不过还在我最终发现了他:undici。

undici在意大利语中是十一的意思,是一个从头开始为node编写的HTTP/1.1客户端,他的特点就是快,据说比内置的HTT模块还要快,下面是基准测试数据:

一、使用
undici是一个npm模块,我们需要安装并引用它:

npm i undici --save

undici对外暴露了一个对象,该对象主要提供了以下API:

1、undici.fetch:发起请求,和浏览器中的 fetch 方法一致,这个是request不支持的,我们在前面的文章中讲过一个技巧将请求copy as fetch,再配合undici.fetch就可以很轻松的完成我们需要的功能。

2、undici.request:发起请求,和 request 库有点类似,该方法支持 Promise。

3、undici.stream:处理文件流,可以用来做接口代理或者文件的下载。

除了上面提到的这些API之外,undici支持通过控制器对象 AbortController 或 EventEmitter 中止一个客户端请求。要在 v15.x 之前的版本使用 AbortController 的需要先安装并导入该模块。最新的 v15.x 版本是不需要的,已默认支持,并且任何发出'abort'事件的ventEmitter实例,都可用作中止控制器。

二、问题

整体看下来,undici已经足够替代request库帮助我们完成我们需要的功能,但是在使用HTTP请求工具的过程中, 我们可能经常会需要维持用户的登录状态(Session机制)并进行下一步的操作,这在request中比较容易实现:

let request = require('request');
const path = require('path');
const { FileCookieStore } = require('tough-cookie-file-store');
const cookieJar = request.jar(new FileCookieStore(path.join(__dirname, './cookies.json')));
request = request.defaults({ jar: cookieJar });

request({
	url: 'https://www.deanhan.cn'
});

借助tough-cookie-fire-store提供的FileCookieStore,我们可以不用关心cookie的存储和传递,一切都是自动进行,比如上面的代码,如果运行之后查看当前文件夹下的cookies.json(这个文件需要提前创建,默认值{}),会发现cookie都被记录到了这个文件中,当我们下次请求同域的网址时,会自动从cookies.json中提取对应的cookie并携带上。

三、解决

这个功能很常见,但是在undici中缺不知该如何实现,undici的文档和描述太少了,而且关于它的文章基本都是讲一些基础的使用,很少有涉及关于cookie的自动管理相关的,但是我始终相信它一定是支持这种功能的,经过一番研究,最终找到了正确的使用方法:

const path = require('path');
const undici = require('undici');
const { fetch } = undici;
const { CookieJar, Cookie } = require('tough-cookie');
const { CookieAgent } = require('http-cookie-agent/undici');
const { FileCookieStore } = require('tough-cookie-file-store');
const cookieStore = new FileCookieStore(path.join(__dirname, './cookies.json'));
const jar = new CookieJar(cookieStore);
const agent = new CookieAgent({ cookies: { jar } });
undici.setGlobalDispatcher(agent);

fetch('https://www.deanhan.cn')
.then(res => res.text())
.then(res => console.log(res));

利用http-cookie-agent/undici提供的CookieAgent将FileCookieStore包装成undici可接受的的dispatcher,并通过setGlobalDispatcher方法将其设置为默认的dispatcher,这样之后发送的请求都会默认自动管理cookie的存储和发送。但是这里要注意的是http-cookie-agent/undici对于node有版本的要求,里面使用了?? 空值合并操作符,在低版本的node中会报错,以上代码在v16.16.0版本中测试通过。

  • 支付宝二维码 支付宝
  • 微信二维码 微信
相关文章