可以看到, Request 在 2020.2.11 就被废弃了, 几乎接触过Node的人都接触过Request, 通过看到一个个库的废弃, 停止支持以及转手, 我们可以看到开源事业的艰辛
image.png
当然, 既然Request废弃了, 我们也得继续找个靠谱的请求库啦! 那就是got
GOT
下图时官方文档中将 got
于 request
, node-fetch
, ky
, axios
, superagent
这几个常用的HTTP请求库功能上的对比, 可以看到got
的功能还算全面, 虽然不支持浏览器端使用...
性能
从其他HTTP请求库迁移到Got
你可能觉得迁移会很麻烦, 但是并不是. ?
让我们从Request的文档中拿出第一个例子:
const request = require('request');
request('https://google.com', (error, response, body) => {
console.log('error:', error);
console.log('statusCode:', response && response.statusCode);
console.log('body:', body);
});
使用GOT, 可以这样写:
const got = require('got');
(async () => {
try {
const response = await got('https://google.com');
console.log('statusCode:', response.statusCode);
console.log('body:', response.body);
} catch (error) {
console.log('error:', error);
}
})();
看起来很棒, 是不是? ?
Request 和 Got 都支持 http.request
的选项.
这些 Got 选项和 Request 的一样:
url
(+ 我们也接受 URL
实例!)body
followRedirect
encoding
maxRedirects
所以如果你很熟悉他们, 你可以很好的上手.
哦, 还有一件事... 没有time
选项. 假设 这是对的.
可读性对于我们来说很重要, 所以我们给这些选项重新命名:
qs
→ searchParams
strictSSL
→ rejectUnauthorized
gzip
→ decompress
jar
→ cookieJar
(接受tough-cookie
库生成的)更清楚了, 不是吗?
timeout
选项 有了一些额外的功能. 你可以查看 设置特定事件超时!
searchParams
选项 总是使用 URLSearchParams
除非它是字符串string
.
使用streams的话, 只需要 调用got.stream(url, options)
或者 got(url, {isStream: true, ...}
).
json
选项不是boolean
类型, 而是 Object
类型. 他将被序列化并当作body使用.form
选项是 Object
类型. 他可以是一个普通对象或者一个form-data
实例.oauth
/hawk
/aws
/httpSignature
选项. 标记请求, 你需要创建一个自定义实例.agentClass
/agentOptions
/pool
选项.forever
选项. 你需要使用forever-agent.proxy
选项. 你需要使用pass a custom agent.auth
选项. 你需要使用 username
/ password
代替.baseUrl
选项. 使用 prefixUrl
代替, 如果不存在就用斜杠代替. 除非URL是一个实例, 否则它将始终是前置.removeRefererHeader
选项. 你可以移除 referer 头 在beforeRequest
钩子里:const gotInstance = got.extend({
hooks: {
beforeRequest: [
options => {
delete options.headers.referer;
}
]
}
});
gotInstance(url, options);
jsonReviver
/jsonReplacer
选项, 但是你可以使用钩子来解决:const gotInstance = got.extend({
hooks: {
init: [
options => {
if (options.jsonReplacer && options.json) {
options.body = JSON.stringify(options.json, options.jsonReplacer);
delete options.json;
}
}
],
beforeRequest: [
options => {
if (options.responseType === 'json' && options.jsonReviver) {
options.responseType = 'text';
options.customJsonResponse = true;
}
}
],
afterResponse: [
response => {
const {options} = response.request;
if (options.jsonReviver && options.customJsonResponse) {
response.body = JSON.parse(response.body, options.jsonReviver);
}
return response;
}
]
}
});
gotInstance(url, options);
钩子是非常有用的, 不是吗? 查看更多 看看钩子还能实现什么.
让我们快速看下 Request 的文档中的另一个示例:
http.createServer((request, response) => {
if (request.url === '/doodle.png') {
request.pipe(request('https://example.com/doodle.png')).pipe(response);
}
});
很酷的功能是, Request 可以代理请求头和流, 当然Got也能做到:
const stream = require('stream');
const {promisify} = require('util');
const got = require('got');
const pipeline = promisify(stream.pipeline);
http.createServer(async (request, response) => {
if (request.url === '/doodle.png') {
// 当有人向我们的服务器发出请求时,我们会收到一个body和一些请求头.
// 这些被传递给Got. 代理将会将数据下载到我们服务器,
// 所以你不必使用`response.writeHead(statusCode, headers)` 和 `response.end(body)`.
// 这些将自动完成.
await pipeline(
got.stream('https://example.com/doodle.png'),
response
);
}
});
一切都没有真正改变. 只是记得使用 got.stream(url, options)
或者 got(url, {isStream: true, …})
. 仅此而已!