nodejs想直接请求第三方接口,比如微信登录的,那么appsecret这些肯定放在后端去请求比较安全。以前常用的是request模块,下面简介介绍一下基本用法。但是request目前已不在维护,下面也会介绍一些靠谱的替代方案。

一、request以及request-promise简单介绍

  request以及request-promise是服务端发起请求的工具包。下面是一些基本用法(2种用法类似)

1、默认get请求



var request = require('request');
request('请求url', function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body) // 请求成功的处理逻辑,注意body是json字符串
}
});


2、post请求



var request = require('request');
var url="请求url";
var requestData="需要传输的数据";
request({
url: url,
method: "POST",
json: true,
headers: {
"content-type": "application/json",
},
body: JSON.stringify(requestData)
}, function(error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body) // 请求成功的处理逻辑
}
});


3、POST form格式上传数据



request.post({url:'', form:{key:'value'}}, function(error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body) // 请求成功的处理逻辑
}
})


  注意:一般使用还是使用request-promise,可以使用await



var rp = require('request-promise')

let wxLogin = async (ctx, next) => {
...
let _wxUrl = `https://api.weixin.qq.com/sns/jscode2session?appid=${wxConfig.appid}&secret=${wxConfig.secret}&js_code=${code}&grant_type=authorization_code`
let result = await rp(_wxUrl)
let _result = JSON.parse(result)
...
}


4、request-promise 发送带 cookie 的请求

  npm 上面的写法,使用了 tough-cookie 模块



let tough = require('tough-cookie');

// Easy creation of the cookie - see tough-cookie docs for details
let cookie = new tough.Cookie({
key: "some_key",
value: "some_value",
domain: 'api.mydomain.com',
httpOnly: true,
maxAge: 31536000
});

// Put cookie in an jar which can be used across multiple requests
let cookiejar = rp.jar();
cookiejar.setCookie(cookie, 'https://api.mydomain.com');
// ...all requests to https://api.mydomain.com will include the cookie

let options = {
uri: 'https://api.mydomain.com/...',
jar: cookiejar // Tells rp to include cookies in jar that match uri
};

rp(options)
.then(function (body) {
// Request succeeded...
})
.catch(function (err) {
// Request failed...
});




  还有一种写法,是 github 的 issue 上看的:这种写法不需要 tough-cookie 模块,把使用 tough-cookie 模块的步骤改成 ​​rp.cookie('' + cookie)​​ 即可,即先把 cookie 转化成字符串(如:​​'connect.sid=s%3AWWUQ9f5g4HnqxC02B7qwKO_Rx9nDbubu.1GZuzQ4rQCE8NZQVaK74ogwURgC83b5gKm7FQrVT%2F2Q; Path=/; HttpOnly'​​),然后传给 rp.cookie()



let cookies = res.headers['set-cookie'];
console.log(cookies);

let cookie_1 = rp.cookie('' + cookies[1]);
console.log(cookie_1);

let cookie_0 = rp.cookie('' + cookies[0]);
console.log(cookie_0);

let cookiejar = rp.jar();
cookiejar.setCookie(cookie_1, url);
cookiejar.setCookie(cookie_0, url);

let options = {
uri: url,
method: 'GET',
jar: cookiejar
};

rp(options).then(function (body) {
console.log(body);
})


二、替代方案

  Request 在 2020.2.11 就被废弃了, 几乎接触过Node的人都接触过Request, 通过看到一个个库的废弃, 停止支持以及转手, 我们可以看到开源事业的艰辛。

推荐一:替代库got

  当然, 既然Request废弃了, 我们也得继续找个靠谱的请求库啦。那就是​got




1、性能对比

  下图是官方文档中将 ​​got​​ 与 ​​request​​, ​​node-fetch​​, ​​ky​​, ​​axios​​, ​​superagent​​这几个常用的HTTP请求库功能上的对比, 可以看到​​got​​的功能还算全面, 虽然不支持浏览器端使用。整体来说,还算不错。

nodejs后台如何请求第三方接口request-promise简介及其废弃后的替代方案推荐got、axios_请求头

2、从 Request 迁移

  你可能觉得迁移会很麻烦, 但是并不是。让我们从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);
}
})();


3、具体用法看官方文档,这里截取一些




  重大变化

  • ​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, …})​​. 仅此而已!

推荐二、替代库Axios

  与浏览器端使用差不多,具体不多说

  推荐这2款,感觉还不错。