@maiyunnet/kebab 9.3.1 → 9.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/doc/kebab-rag.md +1 -1
- package/index.d.ts +1 -1
- package/index.js +1 -1
- package/lib/undici/response.d.ts +1 -1
- package/package.json +1 -1
- package/sys/child.js +37 -19
package/doc/kebab-rag.md
CHANGED
|
@@ -1360,7 +1360,7 @@ index/variables/VER.md
|
|
|
1360
1360
|
|
|
1361
1361
|
# Variable: VER
|
|
1362
1362
|
|
|
1363
|
-
> `const` **VER**: `"9.3.
|
|
1363
|
+
> `const` **VER**: `"9.3.2"` = `'9.3.2'`
|
|
1364
1364
|
|
|
1365
1365
|
Defined in: [index.ts:10](https://github.com/maiyunnet/kebab/blob/master/index.ts#L10)
|
|
1366
1366
|
|
package/index.d.ts
CHANGED
package/index.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* --- 本文件用来定义每个目录实体地址的常量 ---
|
|
7
7
|
*/
|
|
8
8
|
/** --- 当前系统版本号 --- */
|
|
9
|
-
export const VER = '9.3.
|
|
9
|
+
export const VER = '9.3.2';
|
|
10
10
|
// --- 服务端用的路径 ---
|
|
11
11
|
const imu = decodeURIComponent(import.meta.url).replace('file://', '').replace(/^\/(\w:)/, '$1');
|
|
12
12
|
/** --- /xxx/xxx --- */
|
package/lib/undici/response.d.ts
CHANGED
|
@@ -31,7 +31,7 @@ export declare class Response {
|
|
|
31
31
|
/**
|
|
32
32
|
* --- 获取响应读取流对象 ---
|
|
33
33
|
*/
|
|
34
|
-
getStream(): (import("undici/types/readable").default & undici.Dispatcher.BodyMixin) |
|
|
34
|
+
getStream(): zlib.BrotliDecompress | zlib.Gunzip | zlib.Inflate | (import("undici/types/readable").default & undici.Dispatcher.BodyMixin) | null;
|
|
35
35
|
/**
|
|
36
36
|
* --- 获取原生响应读取流对象 ---
|
|
37
37
|
*/
|
package/package.json
CHANGED
package/sys/child.js
CHANGED
|
@@ -26,9 +26,12 @@ const hbTimer = setInterval(function () {
|
|
|
26
26
|
pid: process.pid
|
|
27
27
|
});
|
|
28
28
|
}, 10_000);
|
|
29
|
-
/**
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
/**
|
|
30
|
+
* --- 证书持久化 Map,key 为 keyPath|certPath ---
|
|
31
|
+
* --- 防止 reload 时证书文件处于更新空隙期(旧文件已删、新文件未写入)导致证书丢失 ---
|
|
32
|
+
*/
|
|
33
|
+
const certList = new Map();
|
|
34
|
+
/** --- servername → certList mapKey 索引缓存 --- */
|
|
32
35
|
let certHostIndex = {};
|
|
33
36
|
/** --- 默认证书 --- */
|
|
34
37
|
let defaultSc;
|
|
@@ -83,25 +86,26 @@ async function run() {
|
|
|
83
86
|
http2Server = http2.createSecureServer({
|
|
84
87
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
85
88
|
'SNICallback': (servername, cb) => {
|
|
89
|
+
// --- 每 24 小时自动重新加载一次证书,确保证书更新后能被及时加载到内存中 ---
|
|
86
90
|
if (Date.now() - certLastLoad > 60_000 * 60 * 24) {
|
|
87
91
|
// --- 不能用异步,不要干扰 SNI 进程 ---
|
|
88
92
|
reloadCert().catch(e => {
|
|
89
93
|
lCore.display('[CHILD][run] reloadCert error', e);
|
|
90
94
|
});
|
|
91
95
|
}
|
|
92
|
-
const
|
|
93
|
-
if (
|
|
94
|
-
cb(null, certList
|
|
96
|
+
const cachedKey = certHostIndex[servername];
|
|
97
|
+
if (cachedKey !== undefined) {
|
|
98
|
+
cb(null, certList.get(cachedKey).sc);
|
|
95
99
|
return;
|
|
96
100
|
}
|
|
97
101
|
// --- 查找 servername ---
|
|
98
|
-
for (
|
|
99
|
-
if (!
|
|
102
|
+
for (const [mapKey, item] of certList) {
|
|
103
|
+
if (!item.cert.checkHost(servername)) {
|
|
100
104
|
continue;
|
|
101
105
|
}
|
|
102
106
|
// --- 找到 ---
|
|
103
|
-
cb(null,
|
|
104
|
-
certHostIndex[servername] =
|
|
107
|
+
cb(null, item.sc);
|
|
108
|
+
certHostIndex[servername] = mapKey;
|
|
105
109
|
return;
|
|
106
110
|
}
|
|
107
111
|
if (defaultSc) {
|
|
@@ -488,18 +492,28 @@ async function reload() {
|
|
|
488
492
|
}
|
|
489
493
|
/**
|
|
490
494
|
* --- 重新加载证书对 ---
|
|
495
|
+
* --- 采用增量更新策略:新证书加载成功则覆盖旧值,加载失败(文件更新空隙期)则保留旧证书 ---
|
|
491
496
|
*/
|
|
492
497
|
async function reloadCert() {
|
|
493
498
|
certLastLoad = Date.now();
|
|
494
|
-
|
|
499
|
+
/** --- 本次配置中出现的 mapKey 集合,用于事后清理已下线的证书 --- */
|
|
500
|
+
const newKeys = new Set();
|
|
501
|
+
/** --- 配置文件是否成功加载,未成功则不清理 Map,防止误删全部证书 --- */
|
|
502
|
+
let configLoaded = false;
|
|
495
503
|
try {
|
|
496
504
|
const certConfig = await lFs.getContent(kebab.CONF_CWD + 'cert.json', 'utf8');
|
|
497
505
|
if (certConfig) {
|
|
498
506
|
const certs = lText.parseJson(certConfig);
|
|
507
|
+
configLoaded = true;
|
|
499
508
|
for (const item of certs) {
|
|
500
|
-
const
|
|
501
|
-
const
|
|
509
|
+
const keyPath = lText.isRealPath(item.key) ? item.key : kebab.CERT_CWD + item.key;
|
|
510
|
+
const certPath = lText.isRealPath(item.cert) ? item.cert : kebab.CERT_CWD + item.cert;
|
|
511
|
+
const mapKey = keyPath + '|' + certPath;
|
|
512
|
+
newKeys.add(mapKey);
|
|
513
|
+
const key = await lFs.getContent(keyPath, 'utf8');
|
|
514
|
+
const cert = await lFs.getContent(certPath, 'utf8');
|
|
502
515
|
if (!cert || !key) {
|
|
516
|
+
// --- 文件不存在(可能正在更新),保留旧证书(如果有) ---
|
|
503
517
|
continue;
|
|
504
518
|
}
|
|
505
519
|
const certo = new crypto.X509Certificate(cert);
|
|
@@ -507,18 +521,22 @@ async function reloadCert() {
|
|
|
507
521
|
'key': key,
|
|
508
522
|
'cert': cert
|
|
509
523
|
});
|
|
510
|
-
|
|
511
|
-
'cert': certo,
|
|
512
|
-
'sc': sc
|
|
513
|
-
});
|
|
524
|
+
certList.set(mapKey, { 'cert': certo, 'sc': sc });
|
|
514
525
|
}
|
|
515
526
|
}
|
|
516
527
|
}
|
|
517
528
|
catch {
|
|
518
529
|
// --- NOTHING ---
|
|
519
530
|
}
|
|
520
|
-
|
|
521
|
-
|
|
531
|
+
// --- 仅在配置文件加载成功时,移除已从配置中下线的证书 ---
|
|
532
|
+
if (configLoaded) {
|
|
533
|
+
for (const key of certList.keys()) {
|
|
534
|
+
if (!newKeys.has(key)) {
|
|
535
|
+
certList.delete(key);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
defaultSc = certList.size > 0 ? certList.values().next().value.sc : undefined;
|
|
522
540
|
certHostIndex = {};
|
|
523
541
|
}
|
|
524
542
|
// --- 接收主进程回传信号,主要用来 reload,restart ---
|