From 3db216f515ba404cb4330fdab452971b22a50f08 Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Tue, 22 Oct 2024 01:01:04 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E7=94=B3=E8=AF=B7=E8=AF=81=E4=B9=A6?= =?UTF-8?q?=E6=B2=A1=E6=9C=89=E4=BD=BF=E7=94=A8=E5=88=B0=E7=B3=BB=E7=BB=9F?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E7=9A=84http=E4=BB=A3=E7=90=86=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/core/acme-client/package.json | 1 + packages/core/acme-client/src/agents.js | 101 ++++++++++++++++++ packages/core/acme-client/src/api.js | 1 + packages/core/acme-client/src/axios.js | 35 ++++-- packages/core/acme-client/src/http.js | 14 +-- packages/core/acme-client/src/index.js | 1 + packages/core/acme-client/types/index.d.ts | 1 + packages/core/basic/src/utils/util.request.ts | 12 +++ packages/libs/lib-server/package.json | 1 + .../settings/service/sys-settings-service.ts | 9 +- 10 files changed, 151 insertions(+), 25 deletions(-) create mode 100644 packages/core/acme-client/src/agents.js diff --git a/packages/core/acme-client/package.json b/packages/core/acme-client/package.json index d9dd69ce1..5ed6a0794 100644 --- a/packages/core/acme-client/package.json +++ b/packages/core/acme-client/package.json @@ -20,6 +20,7 @@ "asn1js": "^3.0.5", "axios": "^1.7.2", "debug": "^4.3.5", + "http-proxy-agent": "^7.0.2", "https-proxy-agent": "^7.0.5", "node-forge": "^1.3.1" }, diff --git a/packages/core/acme-client/src/agents.js b/packages/core/acme-client/src/agents.js new file mode 100644 index 000000000..ca182059f --- /dev/null +++ b/packages/core/acme-client/src/agents.js @@ -0,0 +1,101 @@ +const nodeHttp = require('node:http'); +const https = require('node:https'); +const { HttpProxyAgent } = require('http-proxy-agent'); +const { HttpsProxyAgent } = require('https-proxy-agent'); +const { log } = require('./logger'); + +function createAgent(opts = {}) { + let httpAgent; + let + httpsAgent; + const httpProxy = process.env.HTTP_PROXY || process.env.http_proxy; + if (httpProxy) { + log(`acme use httpProxy:${httpProxy}`); + httpAgent = new HttpProxyAgent(httpProxy, opts); + } + else { + httpAgent = new nodeHttp.Agent(opts); + } + const httpsProxy = process.env.HTTPS_PROXY || process.env.https_proxy; + if (httpsProxy) { + log(`acme use httpsProxy:${httpsProxy}`); + httpsAgent = new HttpsProxyAgent(httpsProxy, opts); + } + else { + httpsAgent = new https.Agent(opts); + } + return { + httpAgent, + httpsAgent, + }; +} + +let defaultAgents = createAgent(); + +function getGlobalAgents() { + return defaultAgents; +} + +function setGlobalProxy(opts) { + log('acme setGlobalProxy:', opts); + if (opts.httpProxy) { + process.env.HTTP_PROXY = opts.httpProxy; + } + if (opts.httpsProxy) { + process.env.HTTPS_PROXY = opts.httpsProxy; + } + + defaultAgents = createAgent(); +} + +class HttpError extends Error { + constructor(error) { + super(error || error.message); + if (!error) { + return; + } + + if (error.message.indexOf('ssl3_get_record:wrong version number') >= 0) { + this.message = 'http协议错误,服务端要求http协议,请检查是否使用了https请求'; + } + + this.name = error.name; + this.code = error.code; + this.cause = error.cause; + + if (error.response) { + this.status = error.response.status; + this.statusText = error.response.statusText; + this.response = { + data: error.response.data, + }; + } + + let url = ''; + if (error.config) { + this.request = { + baseURL: error.config.baseURL, + url: error.config.url, + method: error.config.method, + params: error.config.params, + data: error.config.data, + }; + url = error.config.baseURL + error.config.url; + } + if (url) { + this.message = `${this.message}:${url}`; + } + + delete error.response; + delete error.config; + delete error.request; + // logger.error(error); + } +} + +module.exports = { + setGlobalProxy, + createAgent, + getGlobalAgents, + HttpError, +}; diff --git a/packages/core/acme-client/src/api.js b/packages/core/acme-client/src/api.js index 9c251ca5b..70e21b5b6 100644 --- a/packages/core/acme-client/src/api.js +++ b/packages/core/acme-client/src/api.js @@ -30,6 +30,7 @@ class AcmeApi { } } } + console.log(locationUrl, mapping); return locationUrl; } diff --git a/packages/core/acme-client/src/axios.js b/packages/core/acme-client/src/axios.js index 84b0cc554..2c54c0f5a 100644 --- a/packages/core/acme-client/src/axios.js +++ b/packages/core/acme-client/src/axios.js @@ -1,11 +1,11 @@ /** * Axios instance */ - const axios = require('axios'); const { parseRetryAfterHeader } = require('./util'); const { log } = require('./logger'); const pkg = require('./../package.json'); +const Agents = require('./agents'); const { AxiosError } = axios; @@ -24,8 +24,8 @@ instance.defaults.acmeSettings = { httpsChallengePort: 443, tlsAlpnChallengePort: 443, - retryMaxAttempts: 5, - retryDefaultDelay: 5, + retryMaxAttempts: 3, + retryDefaultDelay: 3, }; // instance.defaults.proxy = { // host: '192.168.34.139', @@ -56,19 +56,26 @@ function isRetryableError(error) { /* https://github.com/axios/axios/blob/main/lib/core/settle.js */ function validateStatus(response) { - const validator = response.config.retryValidateStatus; - + if (!response) { + return new Error('Response is undefined'); + } + let validator = null; + if (response.config) { + validator = response.config.retryValidateStatus; + } if (!response.status || !validator || validator(response.status)) { return response; } - throw new AxiosError( + const err = new AxiosError( `Request failed with status code ${response.status}`, (Math.floor(response.status / 100) === 4) ? AxiosError.ERR_BAD_REQUEST : AxiosError.ERR_BAD_RESPONSE, response.config, response.request, response, ); + + throw new Agents.HttpError(err); } /* Pass all responses through the error interceptor */ @@ -76,8 +83,17 @@ instance.interceptors.request.use((config) => { if (!('retryValidateStatus' in config)) { config.retryValidateStatus = config.validateStatus; } - config.validateStatus = () => false; + + const agents = Agents.getGlobalAgents(); + // if (config.skipSslVerify) { + // logger.info('跳过SSL验证'); + // agents = createAgent({ rejectUnauthorized: false } as any); + // } + // delete config.skipSslVerify; + config.httpsAgent = agents.httpsAgent; + config.httpAgent = agents.httpAgent; + config.proxy = false; // 必须 否则还会走一层代理, return config; }); @@ -86,7 +102,7 @@ instance.interceptors.response.use(null, async (error) => { const { config, response } = error; if (!config) { - return Promise.reject(error); + return Promise.reject(new Agents.HttpError(error)); } /* Pick up errors we want to retry */ @@ -115,6 +131,9 @@ instance.interceptors.response.use(null, async (error) => { } } + if (!response) { + return Promise.reject(new Agents.HttpError(error)); + } /* Validate and return response */ return validateStatus(response); }); diff --git a/packages/core/acme-client/src/http.js b/packages/core/acme-client/src/http.js index d2afec334..2e2915f6e 100644 --- a/packages/core/acme-client/src/http.js +++ b/packages/core/acme-client/src/http.js @@ -3,21 +3,9 @@ */ const { createHmac, createSign, constants: { RSA_PKCS1_PADDING } } = require('crypto'); -const { HttpsProxyAgent } = require('https-proxy-agent'); const { getJwk } = require('./crypto'); const { log } = require('./logger'); -const axios1 = require('./axios'); - -const httpsProxy = process.env.HTTPS_PROXY || process.env.https_proxy; -let httpsAgent = null; -if (httpsProxy) { - httpsAgent = new HttpsProxyAgent(httpsProxy); - log(`use https_proxy:${httpsProxy}`); -} -const axios = axios1.create({ - proxy: false, - httpsAgent, -}); +const axios = require('./axios'); /** * ACME HTTP client diff --git a/packages/core/acme-client/src/index.js b/packages/core/acme-client/src/index.js index 65276df41..b0a58842c 100644 --- a/packages/core/acme-client/src/index.js +++ b/packages/core/acme-client/src/index.js @@ -39,6 +39,7 @@ exports.forge = require('./crypto/forge'); */ exports.axios = require('./axios'); +exports.agents = require('./agents'); /** * Logger diff --git a/packages/core/acme-client/types/index.d.ts b/packages/core/acme-client/types/index.d.ts index 9178c840d..77a0122dc 100644 --- a/packages/core/acme-client/types/index.d.ts +++ b/packages/core/acme-client/types/index.d.ts @@ -192,6 +192,7 @@ export const forge: CryptoLegacyInterface; export const axios: AxiosInstance; +export const agents: any; /** * Logger */ diff --git a/packages/core/basic/src/utils/util.request.ts b/packages/core/basic/src/utils/util.request.ts index 6785654a9..db9bd67ba 100644 --- a/packages/core/basic/src/utils/util.request.ts +++ b/packages/core/basic/src/utils/util.request.ts @@ -35,6 +35,14 @@ export class HttpError extends Error { params: error.config?.params, data: error.config?.data, }; + let url = error.config?.url; + if (error.config?.baseURL) { + url = error.config?.baseURL + url; + } + if (url) { + this.message = `${this.message} : ${url}`; + } + this.response = { data: error.response?.data, }; @@ -62,6 +70,10 @@ export function setGlobalProxy(opts: { httpProxy?: string; httpsProxy?: string } defaultAgents = createAgent(); } +export function getGlobalAgents() { + return defaultAgents; +} + /** * @description 创建请求实例 */ diff --git a/packages/libs/lib-server/package.json b/packages/libs/lib-server/package.json index a21940761..2cf0adead 100644 --- a/packages/libs/lib-server/package.json +++ b/packages/libs/lib-server/package.json @@ -27,6 +27,7 @@ "license": "AGPL", "dependencies": { "@certd/basic": "^1.26.10", + "@certd/acme-client": "^1.26.10", "@certd/pipeline": "^1.26.10", "@midwayjs/cache": "~3.14.0", "@midwayjs/core": "~3.17.1", diff --git a/packages/libs/lib-server/src/system/settings/service/sys-settings-service.ts b/packages/libs/lib-server/src/system/settings/service/sys-settings-service.ts index 5d3f2a8f3..7ae277b1b 100644 --- a/packages/libs/lib-server/src/system/settings/service/sys-settings-service.ts +++ b/packages/libs/lib-server/src/system/settings/service/sys-settings-service.ts @@ -7,7 +7,7 @@ import { BaseSettings, SysInstallInfo, SysPrivateSettings, SysPublicSettings, Sy import * as _ from 'lodash-es'; import { BaseService } from '../../../basic/index.js'; import { logger, setGlobalProxy } from '@certd/basic'; - +import { agents } from '@certd/acme-client'; /** * 设置 */ @@ -23,7 +23,6 @@ export class SysSettingsService extends BaseService { getRepository() { return this.repository; } - async getById(id: any): Promise { const entity = await this.info(id); if (!entity) { @@ -129,10 +128,12 @@ export class SysSettingsService extends BaseService { async reloadPrivateSettings() { const bean = await this.getPrivateSettings(); if (bean.httpProxy || bean.httpsProxy) { - setGlobalProxy({ + const opts = { httpProxy: bean.httpProxy, httpsProxy: bean.httpsProxy, - }); + }; + setGlobalProxy(opts); + agents.setGlobalProxy(opts); } }