feat: 更新助手配置,添加应用ID和URL,优化身份验证和代理逻辑
This commit is contained in:
@@ -51,11 +51,11 @@ export class AssistantInit extends AssistantConfig {
|
||||
return this.#query;
|
||||
}
|
||||
get baseURL() {
|
||||
return `${this.getConfig()?.pageApi || 'https://kevisual.cn'}/api/router`;
|
||||
return `${this.getConfig()?.app?.url || 'https://kevisual.cn'}/api/router`;
|
||||
}
|
||||
setQuery(query?: Query) {
|
||||
this.#query = query || new Query({
|
||||
url: `${this.getConfig()?.pageApi || 'https://kevisual.cn'}/api/router`,
|
||||
url: `${this.getConfig()?.app?.url || 'https://kevisual.cn'}/api/router`,
|
||||
});
|
||||
}
|
||||
checkConfigPath() {
|
||||
@@ -92,6 +92,16 @@ export class AssistantInit extends AssistantConfig {
|
||||
if (!checkFileExists(assistantPath, true)) {
|
||||
this.setConfig(this.getDefaultInitAssistantConfig());
|
||||
console.log(chalk.green('助手配置文件assistant-config.json创建成功'));
|
||||
} else {
|
||||
const config = this.getConfig();
|
||||
if (!config?.app?.id) {
|
||||
if (!config.app) {
|
||||
config.app = {};
|
||||
}
|
||||
config.app.id = randomId();
|
||||
this.setConfig(config);
|
||||
console.log(chalk.green('助手配置文件assistant-config.json更新成功'));
|
||||
}
|
||||
}
|
||||
}
|
||||
initPnpm() {
|
||||
@@ -120,7 +130,7 @@ export class AssistantInit extends AssistantConfig {
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"start": "pm2 start apps/root/code-center/app.mjs --name root/code-center",
|
||||
"proxy": "pm2 start apps/root/page-proxy/app.mjs --name root/page-proxy"
|
||||
"cnb": "ASSISTANT_CONFIG_DIR=/workspace asst server -s -p 7878"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
@@ -194,20 +204,18 @@ export class AssistantInit extends AssistantConfig {
|
||||
protected getDefaultInitAssistantConfig() {
|
||||
const id = randomId();
|
||||
return {
|
||||
id,
|
||||
app: {
|
||||
url: 'https://kevisual.cn',
|
||||
id,
|
||||
},
|
||||
description: '助手配置文件',
|
||||
docs: "https://kevisual.cn/root/cli-docs/",
|
||||
docs: "https://kevisual.cn/root/cli/docs/",
|
||||
home: '/root/home',
|
||||
proxy: [],
|
||||
apiProxyList: [],
|
||||
share: {
|
||||
enabled: false,
|
||||
name: 'abc',
|
||||
url: 'https://kevisual.cn/ws/proxy',
|
||||
},
|
||||
watch: {
|
||||
enabled: true,
|
||||
},
|
||||
} as AssistantConfigData;
|
||||
}
|
||||
getHttps() {
|
||||
|
||||
@@ -3,14 +3,72 @@ import http from 'node:http';
|
||||
import { LocalProxy } from './local-proxy.ts';
|
||||
import { assistantConfig, app } from '@/app.ts';
|
||||
import { log, logger } from '@/module/logger.ts';
|
||||
import { getToken } from '@/module/http-token.ts';
|
||||
import { getTokenUserCache } from '@/routes/index.ts';
|
||||
const localProxy = new LocalProxy({});
|
||||
localProxy.initFromAssistantConfig(assistantConfig);
|
||||
|
||||
/**
|
||||
* 过滤访问的资源,允许谁访问
|
||||
* @param req
|
||||
* @param res
|
||||
* @returns
|
||||
*/
|
||||
const authFilter = async (req: http.IncomingMessage, res: http.ServerResponse) => {
|
||||
const _assistantConfig = assistantConfig.getCacheAssistantConfig();
|
||||
const auth = _assistantConfig?.auth || {};
|
||||
const share = auth.share || 'protected';
|
||||
const noAdmin = !auth.username;
|
||||
if (noAdmin) return false;
|
||||
const admin = auth.username;
|
||||
const admins = auth.admin || [];
|
||||
if (admin) {
|
||||
admins.push(admin);
|
||||
}
|
||||
const url = new URL(req.url, 'http://localhost');
|
||||
const pathname = decodeURIComponent(url.pathname);
|
||||
// 放开 /
|
||||
if (pathname === '/' || pathname === '/favicon.ico') {
|
||||
return false;
|
||||
}
|
||||
// 放开首页
|
||||
if (pathname.startsWith('/root/home')) {
|
||||
return false;
|
||||
}
|
||||
// 放开api, 以 /api, /v1, /client, /serve 开头的请求
|
||||
const openApiPaths = ['/api', '/v1', '/client', '/serve'];
|
||||
for (const openPath of openApiPaths) {
|
||||
if (pathname.startsWith(openPath)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (share === 'public') {
|
||||
return false;
|
||||
}
|
||||
const { token } = await getToken(req, res)
|
||||
if (!token) {
|
||||
return false;
|
||||
}
|
||||
const tokenUser = await getTokenUserCache(token);
|
||||
if (share === 'protected' && tokenUser?.code === 200) {
|
||||
return false;
|
||||
}
|
||||
if (share === 'private') {
|
||||
if (tokenUser?.code === 200) {
|
||||
const username = tokenUser?.data?.username;
|
||||
if (admins.includes(username)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
export const proxyRoute = async (req: http.IncomingMessage, res: http.ServerResponse) => {
|
||||
const _assistantConfig = assistantConfig.getCacheAssistantConfig();
|
||||
const home = _assistantConfig?.home || '/root/home';
|
||||
const auth = _assistantConfig?.auth || {};
|
||||
let noAdmin = !auth.username;
|
||||
|
||||
const toSetting = () => {
|
||||
res.writeHead(302, { Location: `/root/cli/setting/` });
|
||||
res.end();
|
||||
@@ -35,9 +93,9 @@ export const proxyRoute = async (req: http.IncomingMessage, res: http.ServerResp
|
||||
return;
|
||||
}
|
||||
// client, api, v1, serve 开头的拦截
|
||||
const apiProxyList = _assistantConfig?.apiProxyList || [];
|
||||
const defaultApiProxy = createApiProxy(_assistantConfig?.pageApi || 'https://kevisual.cn');
|
||||
const apiBackendProxy = [...apiProxyList, ...defaultApiProxy].find((item) => pathname.startsWith(item.path));
|
||||
const apiProxy = _assistantConfig?.api?.proxy || [];
|
||||
const defaultApiProxy = createApiProxy(_assistantConfig?.app?.url || 'https://kevisual.cn');
|
||||
const apiBackendProxy = [...apiProxy, ...defaultApiProxy].find((item) => pathname.startsWith(item.path));
|
||||
if (apiBackendProxy) {
|
||||
log.debug('apiBackendProxy', { apiBackendProxy, url: req.url });
|
||||
return httpProxy(req, res, {
|
||||
@@ -76,6 +134,17 @@ export const proxyRoute = async (req: http.IncomingMessage, res: http.ServerResp
|
||||
...proxyApi,
|
||||
indexPath: _indexPath, // 首页路径
|
||||
});
|
||||
} else if (proxyApi && proxyApi.type === 'http') {
|
||||
log.debug('proxyApi http', { proxyApi, pathname });
|
||||
return httpProxy(req, res, {
|
||||
path: proxyApi.path,
|
||||
target: proxyApi.target,
|
||||
type: 'http',
|
||||
});
|
||||
}
|
||||
const filter = await authFilter(req, res);
|
||||
if (filter) {
|
||||
return res.end('Not Authorized Proxy');
|
||||
}
|
||||
const localProxyProxyList = localProxy.getLocalProxyList();
|
||||
const localProxyProxy = localProxyProxyList.find((item) => pathname.startsWith(item.path));
|
||||
@@ -87,7 +156,7 @@ export const proxyRoute = async (req: http.IncomingMessage, res: http.ServerResp
|
||||
indexPath: localProxyProxy.indexPath,
|
||||
});
|
||||
}
|
||||
const creatCenterProxy = createApiProxy(_assistantConfig?.pageApi || 'https://kevisual.cn', ['/root', '/' + _user]);
|
||||
const creatCenterProxy = createApiProxy(_assistantConfig?.app?.url || 'https://kevisual.cn', ['/root', '/' + _user]);
|
||||
const centerProxy = creatCenterProxy.find((item) => pathname.startsWith(item.path));
|
||||
if (centerProxy) {
|
||||
return httpProxy(req, res, {
|
||||
@@ -103,9 +172,9 @@ export const proxyRoute = async (req: http.IncomingMessage, res: http.ServerResp
|
||||
};
|
||||
|
||||
export const proxyWs = () => {
|
||||
const apiProxyList = assistantConfig.getCacheAssistantConfig()?.apiProxyList || [];
|
||||
const apiProxy = assistantConfig.getCacheAssistantConfig()?.api?.proxy || [];
|
||||
const proxy = assistantConfig.getCacheAssistantConfig()?.proxy || [];
|
||||
const proxyApi = [...apiProxyList, ...proxy].filter((item) => item.ws);
|
||||
const proxyApi = [...apiProxy, ...proxy].filter((item) => item.ws);
|
||||
log.debug('proxyApi ', proxyApi);
|
||||
wsProxy(app.server.server, {
|
||||
apiList: proxyApi,
|
||||
|
||||
Reference in New Issue
Block a user