NodeJS axios 请求自签名在浏览器中有效,但在开玩笑的超级测试案例中无效
NodeJS axios request self signed works in browser but not in jest supertest case
我正在构建一个调用外部 API 的 NodeJS 应用程序。外部 API 使用自签名证书。我尝试设置环境变量 process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'。这可以在正常使用应用程序时忽略证书验证。但是,当使用 Jest Supertest 代理调用 NodeJS 路由时,对同一端点的请求不起作用。
Jest超测用例运行时出现证书验证错误。 在使用 Supertest 代理发送请求时,是否可以接受自签名证书?
npm test
Error: Error: SSL Error: DEPTH_ZERO_SELF_SIGNED_CERT
at Object.dispatchError (/home/node/app/node_modules/jsdom/lib/jsdom/living/xhr-utils.js:54:19)
at EventEmitter.<anonymous> (/home/node/app/node_modules/jsdom/lib/jsdom/living/xmlhttprequest.js:675:20)
at EventEmitter.emit (events.js:323:22)
at Request.<anonymous> (/home/node/app/node_modules/jsdom/lib/jsdom/living/xhr-utils.js:384:47)
at Request.emit (events.js:311:20)
at Request.onRequestResponse (/home/node/app/node_modules/request/request.js:948:10)
at ClientRequest.emit (events.js:311:20)
at HTTPParser.parserOnIncomingClient [as onIncoming] (_http_client.js:603:27)
at HTTPParser.parserOnHeadersComplete (_http_common.js:119:17)
at TLSSocket.socketOnData (_http_client.js:476:22) undefined
NodeJS 内部路由
在通过浏览器访问路由时有效,但在 运行 Jest Supertest 时无效。内部路由是 /internal 并且有效,但是当该代码随后向具有自签名证书的外部 API 发送请求时,自签名证书会导致 500 错误消息。
router.get('/internal', (req, res, next) => {
// Set request values that are specific to this route
const requestOptionsData = { method: `GET`, endpoint: `/external` };
try {
httpCtrl.makeRequest(requestOptionsData).then(result => {
if (result.error) {
return res.status(result.status).json(result.error.message || result.error);
}
return res.status(result.status).json(result);
}).catch((error) => {
console.error(error);
return res.status(500).send(error);
});
} catch (e) {
console.error(e);
return res.status(500).send(e);
}
});
NodeJS 控制器
向外部发出 axios 请求的包装函数 API
httpCtrl.makeRequest = async (requestOptionsData) => {
let result = {};
// Set request options
const requestOptions = httpCtrl.setApiRequestOptions(requestOptionsData);
let response;
try {
response = await axios(requestOptions);
} catch(e) {
result.error = e.toJSON() || e;
console.error(result.error);
result.status = 500;
return result;
}
result.status = response && response.status || 500;
result.data = response && response.data || {};
return result;
}
JEST超测
导致证书错误的测试
const app = require('../app.js');
const supertest = require('supertest');
describe('API routes', () => {
it('GET internal NodeJS route', async done => {
agent
.get('/internal')
.set('Accept', 'application/json')
.send()
.expect(200)
.end((err, res) => {
if (err) {
return done(err);
}
expect(res.status).toBe(200);
return done();
});
});
});
更新:
我尝试在 axios 代理配置中删除 NODE_TLS_REJECT_UNAUTHORIZED 并将 rejectUnauthorized 设置为 false,但仍然遇到同样的问题。通过浏览器使用应用程序时连接有效,但适用于超级测试。
const agent = new https.Agent({
rejectUnauthorized: false
});
const options = {
url: url,
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': `Bearer ${requestOptionsData.jwt}`,
'Host': process.env.ADMIN_API_BASE_URL
},
method: requestOptionsData.method || `GET`,
httpsAgent: agent
}
这是此代理配置的错误:
Error: Error: self signed certificate
at Object.dispatchError (/home/node/app/node_modules/jsdom/lib/jsdom/living/xhr-utils.js:54:19)
at EventEmitter.<anonymous> (/home/node/app/node_modules/jsdom/lib/jsdom/living/xmlhttprequest.js:675:20)
at EventEmitter.emit (events.js:323:22)
at Request.<anonymous> (/home/node/app/node_modules/jsdom/lib/jsdom/living/xhr-utils.js:384:47)
at Request.emit (events.js:311:20)
at Request.onRequestError (/home/node/app/node_modules/request/request.js:877:8)
at ClientRequest.emit (events.js:311:20)
at TLSSocket.socketErrorListener (_http_client.js:426:9)
at TLSSocket.emit (events.js:311:20)
at emitErrorNT (internal/streams/destroy.js:92:8) undefined
console.error controllers/http.ctrl.js:50
我能够使用此 github 问题中的解决方案解决此问题。
我通过将 testEnvironment: 'node' 添加到 jest.config.js 文件来解决它。
我正在构建一个调用外部 API 的 NodeJS 应用程序。外部 API 使用自签名证书。我尝试设置环境变量 process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'。这可以在正常使用应用程序时忽略证书验证。但是,当使用 Jest Supertest 代理调用 NodeJS 路由时,对同一端点的请求不起作用。
Jest超测用例运行时出现证书验证错误。 在使用 Supertest 代理发送请求时,是否可以接受自签名证书?
npm test
Error: Error: SSL Error: DEPTH_ZERO_SELF_SIGNED_CERT
at Object.dispatchError (/home/node/app/node_modules/jsdom/lib/jsdom/living/xhr-utils.js:54:19)
at EventEmitter.<anonymous> (/home/node/app/node_modules/jsdom/lib/jsdom/living/xmlhttprequest.js:675:20)
at EventEmitter.emit (events.js:323:22)
at Request.<anonymous> (/home/node/app/node_modules/jsdom/lib/jsdom/living/xhr-utils.js:384:47)
at Request.emit (events.js:311:20)
at Request.onRequestResponse (/home/node/app/node_modules/request/request.js:948:10)
at ClientRequest.emit (events.js:311:20)
at HTTPParser.parserOnIncomingClient [as onIncoming] (_http_client.js:603:27)
at HTTPParser.parserOnHeadersComplete (_http_common.js:119:17)
at TLSSocket.socketOnData (_http_client.js:476:22) undefined
NodeJS 内部路由
在通过浏览器访问路由时有效,但在 运行 Jest Supertest 时无效。内部路由是 /internal 并且有效,但是当该代码随后向具有自签名证书的外部 API 发送请求时,自签名证书会导致 500 错误消息。
router.get('/internal', (req, res, next) => {
// Set request values that are specific to this route
const requestOptionsData = { method: `GET`, endpoint: `/external` };
try {
httpCtrl.makeRequest(requestOptionsData).then(result => {
if (result.error) {
return res.status(result.status).json(result.error.message || result.error);
}
return res.status(result.status).json(result);
}).catch((error) => {
console.error(error);
return res.status(500).send(error);
});
} catch (e) {
console.error(e);
return res.status(500).send(e);
}
});
NodeJS 控制器
向外部发出 axios 请求的包装函数 API
httpCtrl.makeRequest = async (requestOptionsData) => {
let result = {};
// Set request options
const requestOptions = httpCtrl.setApiRequestOptions(requestOptionsData);
let response;
try {
response = await axios(requestOptions);
} catch(e) {
result.error = e.toJSON() || e;
console.error(result.error);
result.status = 500;
return result;
}
result.status = response && response.status || 500;
result.data = response && response.data || {};
return result;
}
JEST超测
导致证书错误的测试
const app = require('../app.js');
const supertest = require('supertest');
describe('API routes', () => {
it('GET internal NodeJS route', async done => {
agent
.get('/internal')
.set('Accept', 'application/json')
.send()
.expect(200)
.end((err, res) => {
if (err) {
return done(err);
}
expect(res.status).toBe(200);
return done();
});
});
});
更新:
我尝试在 axios 代理配置中删除 NODE_TLS_REJECT_UNAUTHORIZED 并将 rejectUnauthorized 设置为 false,但仍然遇到同样的问题。通过浏览器使用应用程序时连接有效,但适用于超级测试。
const agent = new https.Agent({
rejectUnauthorized: false
});
const options = {
url: url,
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': `Bearer ${requestOptionsData.jwt}`,
'Host': process.env.ADMIN_API_BASE_URL
},
method: requestOptionsData.method || `GET`,
httpsAgent: agent
}
这是此代理配置的错误:
Error: Error: self signed certificate
at Object.dispatchError (/home/node/app/node_modules/jsdom/lib/jsdom/living/xhr-utils.js:54:19)
at EventEmitter.<anonymous> (/home/node/app/node_modules/jsdom/lib/jsdom/living/xmlhttprequest.js:675:20)
at EventEmitter.emit (events.js:323:22)
at Request.<anonymous> (/home/node/app/node_modules/jsdom/lib/jsdom/living/xhr-utils.js:384:47)
at Request.emit (events.js:311:20)
at Request.onRequestError (/home/node/app/node_modules/request/request.js:877:8)
at ClientRequest.emit (events.js:311:20)
at TLSSocket.socketErrorListener (_http_client.js:426:9)
at TLSSocket.emit (events.js:311:20)
at emitErrorNT (internal/streams/destroy.js:92:8) undefined
console.error controllers/http.ctrl.js:50
我能够使用此 github 问题中的解决方案解决此问题。
我通过将 testEnvironment: 'node' 添加到 jest.config.js 文件来解决它。