cra*_*aig 6 javascript client-certificates node.js node-https node-fetch
ADP 的 REST API 要求每次请求时都发送 SSL 证书和私钥。
当我使用“标准 Node.js HTTP(S) 模块”时:
require('dotenv').config()
const fs = require('fs')
const path = require('path')
const certificate_path = path.resolve('../credentials/certificate.pem')
const private_key_path = path.resolve('../credentials/private.key')
const options = {
hostname: 'api.adp.com',
path: '/hr/v2/workers/ABCDEFGHIJKLMNOP',
method: 'GET',
headers: {
'Accept': 'application/json;masked=false',
'Authorization': `Bearer ${process.env.ACCESS_TOKEN}`
},
cert: fs.readFileSync(certificate_path, "utf8"),
key: fs.readFileSync(private_key_path, "utf8"),
};
require('https').get(options, res => {
let data = [];
res.on('data', chunk => {
data.push(chunk);
});
res.on('end', () => {
const workers = JSON.parse(Buffer.concat(data).toString());
for(worker of workers.workers) {
console.log(`Got worker with id: ${worker.associateOID}, name: ${worker.person.legalName.formattedName}`);
}
});
}).on('error', err => {
console.log('Error: ', err.message);
});
Run Code Online (Sandbox Code Playgroud)
该请求按预期工作:
$ node ./standard.js
Got worker with id: ABCDEFGHIJKLMNOP, name: Last, First
Run Code Online (Sandbox Code Playgroud)
但是,当我使用节点获取时:
require('dotenv').config()
const fs = require('fs')
const path = require('path')
const certificate_path = path.resolve('../credentials/certificate.pem')
const private_key_path = path.resolve('../credentials/private.key')
const url = 'https://accounts.adp.com/hr/v2/workers/ABCDEFGHIJKLMNOP'
const options = {
headers: {
'Accept': 'application/json;masked=false',
'Authorization': `Bearer ${process.env.ACCESS_TOKEN}`
},
agent: new require('https').Agent({
cert: fs.readFileSync(certificate_path, "utf8"),
key: fs.readFileSync(private_key_path, "utf8")
})
}
fetch(url,options)
.then((response) => response.json())
.then((body) => {
console.log(body);
});
Run Code Online (Sandbox Code Playgroud)
我收到错误:
$ node ./fetch.js
{
response: {
responseCode: 401,
methodCode: 'GET',
resourceUri: { href: '/hr/v2/workers/ABCDEFGHIJKLMNOP' },
serverRequestDateTime: '2023-03-30T14:25:23.351Z',
applicationCode: {
code: 401,
typeCode: 'error',
message: 'Request did not provide the required two-way TLS certificate'
},
client_ip_adddress: 'a.b.c.d',
'adp-correlationID': '61f76d29-04e1-48b8-be9d-acf459408b2b'
}
}
Run Code Online (Sandbox Code Playgroud)
我在第二种方法中缺少什么?
也许令人惊讶的是,节点的内置fetch()全局不使用传统内置http/https模块提供的HTTP堆栈。
相反,它使用并行的、从头开始的 HTTP 堆栈重写,称为undici。
鉴于 的fetch()HTTP 堆栈完全独立于标准 HTTP 堆栈,因此您可以提供给 et al 的选项http.get不能与 一起使用也就不足为奇了fetch()。
查看文档,您似乎可以传入自定义Dispatcher对象,该对象又可以自定义Client用于连接到服务器的对象。可以Client配置请求中使用的TLS 客户端证书。
不幸的是,此时,node 捆绑的 undici 并未暴露给用户代码;你做不到require()。我没有深入研究内部结构,但您可能必须在项目中安装undici 包,才能访问构建Dispatcher可以提供客户端证书的自定义所需的类。
但请注意,undici 的版本是与 Node 静态捆绑的,因此它将取决于安装的 Node 发行版本。我可以想象由于 undici 的内置版本和打包版本的重复和/或不匹配版本而导致的奇怪错误。当事情被认为稳定时,节点的未来版本可能会公开捆绑的undici。
鉴于上述情况,至少在短期内,我个人会坚持使用传统的http( s) 模块而不是fetch().
我没有看到任何 node-fetch 的导入,因此我假设您正在使用添加到 Node18 的新本机 fetch。新的全局获取(尚)不支持代理选项。
| 归档时间: |
|
| 查看次数: |
2841 次 |
| 最近记录: |