1
This commit is contained in:
97
api/controller_front/static.js
Normal file
97
api/controller_front/static.js
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const axios = require('axios');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 静态 JS 代理/缓存
|
||||||
|
*
|
||||||
|
* 规则:
|
||||||
|
* - 前端请求:GET /static/boss,header 里带 path,例如:
|
||||||
|
* path: https://static.zhipin.com/fe-zhipin-geek/web/chat-new/v5410/static/js/app.4e199352.js
|
||||||
|
* - 从 URL 中取 pathname:/fe-zhipin-geek/web/chat-new/v5410/static/js/app.4e199352.js
|
||||||
|
* - 去掉开头的 /,中间的 / 全部替换为 _,得到本地文件名:
|
||||||
|
* fe-zhipin-geek_web-chat-new_v5410_static_js_app.4e199352.js
|
||||||
|
* - 在项目根目录下的 js 目录保存/读取该文件:./js/<文件名>
|
||||||
|
* - 如果已存在:直接返回本地文件
|
||||||
|
* - 如果不存在:从远程 URL 下载,保存后返回
|
||||||
|
*/
|
||||||
|
module.exports = {
|
||||||
|
'GET /static/boss': async (ctx) => {
|
||||||
|
// 1. 获取原始 URL(优先从 header,兼容 query/body)
|
||||||
|
const urlStr =
|
||||||
|
ctx.get('path') ||
|
||||||
|
ctx.query.path ||
|
||||||
|
(ctx.request.body && ctx.request.body.path);
|
||||||
|
|
||||||
|
if (!urlStr) {
|
||||||
|
ctx.status = 400;
|
||||||
|
ctx.body = { code: 400, message: '缺少 path 参数' };
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let urlObj = new URL(urlStr);
|
||||||
|
|
||||||
|
// 2. 生成本地文件名:去掉开头的 /,中间 / 替换为 _
|
||||||
|
const remotePath = urlObj.pathname || '/';
|
||||||
|
const fileName = remotePath
|
||||||
|
.replace(/^\/+/, '')
|
||||||
|
.replace(/\//g, '_');
|
||||||
|
|
||||||
|
// 根目录下 js 目录
|
||||||
|
const jsRootDir = path.join(process.cwd(), 'static/boss');
|
||||||
|
const localFilePath = path.join(jsRootDir, fileName);
|
||||||
|
|
||||||
|
// 钩子注入:在 JS 中注入自定义 onMessageArrived 钩子
|
||||||
|
const injectOnMessageArrivedHook = (buffer) => {
|
||||||
|
try {
|
||||||
|
let js = buffer.toString('utf8');
|
||||||
|
const needle = 'onMessageArrived:function(e){try{var t=e.payloadBytes,n=S.decode(t);';
|
||||||
|
if (js.includes(needle)) {
|
||||||
|
const hook = `${needle}if(window.Function&&window.Function.__proto__&&typeof window.Function.__proto__.$onMessageArrived==="function"){try{window.Function.__proto__.$onMessageArrived(n);}catch(e){}}`;
|
||||||
|
js = js.replace(needle, hook);
|
||||||
|
return Buffer.from(js, 'utf8');
|
||||||
|
}
|
||||||
|
return buffer;
|
||||||
|
} catch (e) {
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 确保目录存在
|
||||||
|
if (!fs.existsSync(jsRootDir)) {
|
||||||
|
fs.mkdirSync(jsRootDir, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 如果文件已存在,直接返回本地文件(文件内容已是替换后的,无需再次注入)
|
||||||
|
if (fs.existsSync(localFilePath)) {
|
||||||
|
ctx.type = 'application/javascript; charset=utf-8';
|
||||||
|
ctx.body = fs.createReadStream(localFilePath);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 文件不存在:从远程下载并保存(带钩子注入)
|
||||||
|
const response = await axios.get(urlStr, {
|
||||||
|
responseType: 'arraybuffer',
|
||||||
|
timeout: 15000,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.status !== 200) {
|
||||||
|
ctx.status = 502;
|
||||||
|
ctx.body = { code: 502, message: '下载远程 JS 失败' };
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const patched = injectOnMessageArrivedHook(Buffer.from(response.data));
|
||||||
|
|
||||||
|
fs.writeFileSync(localFilePath, patched);
|
||||||
|
|
||||||
|
ctx.type = 'application/javascript; charset=utf-8';
|
||||||
|
ctx.body = patched;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[static/boss] 处理失败:', error);
|
||||||
|
ctx.status = 500;
|
||||||
|
ctx.body = { code: 500, message: '静态资源代理失败', error: error.message };
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -61,7 +61,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// 白名单URL - 不需要token验证的接口
|
// 白名单URL - 不需要token验证的接口
|
||||||
"allowUrls": ["/admin_api/sys_user/login", "/admin_api/sys_user/authorityMenus", "/admin_api/sys_user/register", "/api/user/loginByWeixin", "/file/", "/sys_file/", "/admin_api/win_data/viewLogInfo", "/api/user/wx_auth", '/api/docs', 'api/swagger.json', 'payment/notify', 'payment/refund-notify', 'wallet/transfer_notify', 'user/sms/send', 'user/sms/verify', '/api/version/check','/api/file/upload_file_to_oss_by_auto_work','/api/version/create', 'register', 'send_email_code','/config/remote-code/version'],
|
"allowUrls": ["/admin_api/sys_user/login", "/admin_api/sys_user/authorityMenus", "/admin_api/sys_user/register", "/api/user/loginByWeixin", "/file/", "/sys_file/", "/admin_api/win_data/viewLogInfo", "/api/user/wx_auth", '/api/docs', 'api/swagger.json', 'payment/notify', 'payment/refund-notify', 'wallet/transfer_notify', 'user/sms/send', 'user/sms/verify', '/api/version/check','/api/file/upload_file_to_oss_by_auto_work','/api/version/create', 'register', 'send_email_code','/config/remote-code/version','/api/static/boss'],
|
||||||
|
|
||||||
|
|
||||||
// AI服务配置
|
// AI服务配置
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user