mirror of
https://gitcode.com/JianFeeeee/ModelRouter.git
synced 2026-10-03 23:54:06 +00:00
fix(gui): 缓存解封结果,否则每个请求都要 spawn 一个进程
The auth rule calls readAdminKey() on every outbound request so injection never depends on ordering. Once the sealed-config path shells out to the core, that turns each request into a process spawn: 200 simulated requests took 1012ms and launched 200 cores. Cache the unsealed key against config.yaml's mtime. Editing the config still invalidates it, which is what the auth rule actually needs -- the port rewrite, the first write, and a user edit all change mtime. Measured: 200 requests now cost 10ms and one spawn. Only a successful unseal is cached. Caching a failure would pin an empty key until the config next changes, turning a momentary spawn error into a locked out user.
This commit is contained in:
@ -142,7 +142,17 @@ function readConfigRaw() {
|
||||
// the core generate a *second* master key in the CWD and then fail to decrypt
|
||||
// ("master key changed?"). Electron's CWD is not the profile dir, so this is
|
||||
// not optional: without it the desktop build cannot read its own key back.
|
||||
//
|
||||
// readAdminKey runs on every outbound request, and this spawns a process, so
|
||||
// the result is cached against the config's mtime. Editing the config (or the
|
||||
// port rewrite, or the first write) changes the mtime and invalidates it, which
|
||||
// keeps the "read live so ordering never matters" property the auth rule
|
||||
// depends on.
|
||||
function unsealViaCore() {
|
||||
const st = safeStat(CONFIG_FILE);
|
||||
const stamp = st ? st.mtimeMs : 0;
|
||||
if (unsealCache && unsealCache.stamp === stamp) return unsealCache.key;
|
||||
let key = "";
|
||||
try {
|
||||
const out = execFileSync(
|
||||
CORE_EXE,
|
||||
@ -157,14 +167,29 @@ function unsealViaCore() {
|
||||
// -show-secrets prints one line per credential:
|
||||
// key <name> role=<role> <value>
|
||||
const admin = /^key\s+\S+\s+role=admin\s+(\S+)\s*$/m.exec(out);
|
||||
if (admin && admin[1]) return admin[1];
|
||||
if (admin && admin[1]) key = admin[1];
|
||||
// Tolerate a field-order or spacing change rather than locking the user out.
|
||||
const loose = /role=admin\s+(\S+)/.exec(out);
|
||||
if (loose && loose[1]) return loose[1];
|
||||
if (!key) {
|
||||
const loose = /role=admin\s+(\S+)/.exec(out);
|
||||
if (loose && loose[1]) key = loose[1];
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("unseal via core failed:", e.message);
|
||||
}
|
||||
return "";
|
||||
// Only cache a success. A transient failure must not pin an empty key until
|
||||
// the config next changes, or a momentary spawn error locks the user out.
|
||||
if (key) unsealCache = { stamp, key };
|
||||
return key;
|
||||
}
|
||||
|
||||
let unsealCache = null;
|
||||
|
||||
function safeStat(p) {
|
||||
try {
|
||||
return fs.statSync(p);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
const embeddedBaseUrl = () =>
|
||||
|
||||
Reference in New Issue
Block a user