add resource proxy

This commit is contained in:
熊潇 2025-05-11 15:56:06 +08:00
parent f2cc76a8ea
commit 5de857aca8
4 changed files with 26 additions and 41 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "page-proxy", "name": "page-proxy",
"version": "0.0.4", "version": "0.0.5",
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"type": "module", "type": "module",

View File

@ -14,14 +14,19 @@ import { downloadFileFromMinio } from './proxy/http-proxy.ts';
const pipelineAsync = promisify(pipeline); const pipelineAsync = promisify(pipeline);
const { resources } = config?.proxy || { resources: 'https://minio.xiongxiao.me/resources' }; const { resources } = config?.proxy || { resources: 'https://minio.xiongxiao.me/resources' };
const wrapperResources = (resources: string, urlpath: string) => {
if (urlpath.startsWith('http')) {
return urlpath;
}
return `${resources}/${urlpath}`;
};
const demoData = { const demoData = {
user: 'root', user: 'root',
key: 'codeflow', key: 'codeflow',
appType: 'web-single', // appType: 'web-single', //
version: '1.0.0', version: '1.0.0',
domain: null, domain: null,
type: 'local', // local, oss 默认是oss type: 'oss', // oss 默认是oss
data: { data: {
files: [ files: [
{ {
@ -221,9 +226,9 @@ export class UserApp {
// 将文件名和路径添加到 `data` 对象中 // 将文件名和路径添加到 `data` 对象中
files.forEach((file) => { files.forEach((file) => {
if (file.name === 'index.html') { if (file.name === 'index.html') {
indexHtml = resources + '/' + file.path; indexHtml = wrapperResources(resources, file.path);
} }
data[file.name] = resources + '/' + file.path; data[file.name] = wrapperResources(resources, file.path);
}); });
await redis.set('user:app:exist:' + app + ':' + user, indexHtml + '||etag||true', 'EX', 60 * 60 * 24 * 7); // 7天 await redis.set('user:app:exist:' + app + ':' + user, indexHtml + '||etag||true', 'EX', 60 * 60 * 24 * 7); // 7天
await redis.set('user:app:permission:' + app + ':' + user, JSON.stringify(permission), 'EX', 60 * 60 * 24 * 7); // 7天 await redis.set('user:app:permission:' + app + ':' + user, JSON.stringify(permission), 'EX', 60 * 60 * 24 * 7); // 7天
@ -326,38 +331,9 @@ export const downloadUserAppFiles = async (user: string, app: string, data: type
fs.mkdirSync(uploadFiles, { recursive: true }); fs.mkdirSync(uploadFiles, { recursive: true });
} }
const newFiles = []; const newFiles = [];
try {
if (data.type === 'local') {
// local copy file
for (let i = 0; i < files.length; i++) {
const file = files[i];
const copyFile = path.join(fileStore, file.path);
const destFile = path.join(uploadFiles, file.name);
const destDir = path.dirname(destFile); // 获取目标文件所在的目录路径
// 检查目录是否存在,如果不存在则创建
if (!checkFileExistsSync(destDir)) {
fs.mkdirSync(destDir, { recursive: true }); // 递归创建目录
}
fs.copyFileSync(copyFile, destFile);
// const etag = await setEtag(fs.readFileSync(destFile, 'utf-8'));
const etag = nanoid();
newFiles.push({
name: file.name,
path: destFile.replace(fileStore, '') + '||' + etag,
});
}
}
} catch (err) {
const userApp = new UserApp({ user, app });
userApp.clearCacheData();
return {
data: {
files: [],
},
};
}
if (data.type === 'oss') { if (data.type === 'oss') {
let serverPath = new URL(resources).href + '/'; let serverPath = new URL(resources).href;
let hasIndexHtml = false; let hasIndexHtml = false;
// server download file // server download file
for (let i = 0; i < files.length; i++) { for (let i = 0; i < files.length; i++) {
@ -371,8 +347,9 @@ export const downloadUserAppFiles = async (user: string, app: string, data: type
if (!checkFileExistsSync(destDir)) { if (!checkFileExistsSync(destDir)) {
fs.mkdirSync(destDir, { recursive: true }); // 递归创建目录 fs.mkdirSync(destDir, { recursive: true }); // 递归创建目录
} }
const downloadURL = wrapperResources(serverPath, file.path);
// 下载文件到 destFile // 下载文件到 destFile
await downloadFile(serverPath + file.path, destFile); await downloadFile(downloadURL, destFile);
const etag = nanoid(); const etag = nanoid();
newFiles.push({ newFiles.push({
name: file.name, name: file.name,

View File

@ -227,7 +227,7 @@ export const handleRequest = async (req: http.IncomingMessage, res: http.ServerR
res.write(msg || 'Not Found App\n'); res.write(msg || 'Not Found App\n');
res.end(); res.end();
}; };
if (app === 'ai') { if (app === 'ai' || user === 'resources') {
return aiProxy(req, res, { return aiProxy(req, res, {
createNotFoundPage, createNotFoundPage,
}); });

View File

@ -18,16 +18,24 @@ export const aiProxy = async (
const pathname = _u.pathname; const pathname = _u.pathname;
const params = _u.searchParams; const params = _u.searchParams;
const password = params.get('p'); const password = params.get('p');
const version = params.get('version') || '1.0.0'; let objectName = '';
let owner = '';
const { user, app } = getUserFromRequest(req); const { user, app } = getUserFromRequest(req);
const objectName = pathname.replace(`/${user}/${app}/`, `${user}/${app}/${version}/`); if (user === 'ai') {
const version = params.get('version') || '1.0.0'; // root/ai
objectName = pathname.replace(`/${user}/${app}/`, `${user}/${app}/${version}/`);
owner = user;
} else {
objectName = pathname.replace(`/${user}`, ``); // resources/root/
owner = app;
}
try { try {
const stat = await minioClient.statObject(bucketName, objectName); const stat = await minioClient.statObject(bucketName, objectName);
if (stat.size === 0) { if (stat.size === 0) {
createNotFoundPage('Invalid proxy url'); createNotFoundPage('Invalid proxy url');
return true; return true;
} }
const permissionInstance = new UserPermission({ permission: stat.metaData as Permission, owner: user }); const permissionInstance = new UserPermission({ permission: stat.metaData as Permission, owner: owner });
const loginUser = await getLoginUser(req); const loginUser = await getLoginUser(req);
const checkPermission = permissionInstance.checkPermissionSuccess({ const checkPermission = permissionInstance.checkPermissionSuccess({
username: loginUser?.tokenUser?.username || '', username: loginUser?.tokenUser?.username || '',