perf
This commit is contained in:
parent
98d6dfb6db
commit
cf82967060
@ -31,6 +31,8 @@
|
|||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@kevisual/logger": "^0.0.2",
|
||||||
|
"@kevisual/oss": "^0.0.7",
|
||||||
"@rollup/plugin-commonjs": "^28.0.3",
|
"@rollup/plugin-commonjs": "^28.0.3",
|
||||||
"@rollup/plugin-json": "^6.1.0",
|
"@rollup/plugin-json": "^6.1.0",
|
||||||
"@rollup/plugin-node-resolve": "^16.0.1",
|
"@rollup/plugin-node-resolve": "^16.0.1",
|
||||||
@ -51,7 +53,7 @@
|
|||||||
"@kevisual/permission": "^0.0.1",
|
"@kevisual/permission": "^0.0.1",
|
||||||
"@kevisual/query": "^0.0.17",
|
"@kevisual/query": "^0.0.17",
|
||||||
"@kevisual/query-config": "^0.0.2",
|
"@kevisual/query-config": "^0.0.2",
|
||||||
"@kevisual/router": "0.0.13",
|
"@kevisual/router": "0.0.14",
|
||||||
"@kevisual/use-config": "^1.0.15",
|
"@kevisual/use-config": "^1.0.15",
|
||||||
"archiver": "^7.0.1",
|
"archiver": "^7.0.1",
|
||||||
"busboy": "^1.6.0",
|
"busboy": "^1.6.0",
|
||||||
|
32
pnpm-lock.yaml
generated
32
pnpm-lock.yaml
generated
@ -13,7 +13,7 @@ importers:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@kevisual/code-center-module':
|
'@kevisual/code-center-module':
|
||||||
specifier: 0.0.18
|
specifier: 0.0.18
|
||||||
version: 0.0.18(@kevisual/auth@1.0.5)(@kevisual/router@0.0.13)(@kevisual/use-config@1.0.15(dotenv@16.4.7))(ioredis@5.6.1)(pg@8.13.3)(sequelize@6.37.7(pg@8.13.3))
|
version: 0.0.18(@kevisual/auth@1.0.5)(@kevisual/router@0.0.14)(@kevisual/use-config@1.0.15(dotenv@16.4.7))(ioredis@5.6.1)(pg@8.13.3)(sequelize@6.37.7(pg@8.13.3))
|
||||||
'@kevisual/permission':
|
'@kevisual/permission':
|
||||||
specifier: ^0.0.1
|
specifier: ^0.0.1
|
||||||
version: 0.0.1
|
version: 0.0.1
|
||||||
@ -24,8 +24,8 @@ importers:
|
|||||||
specifier: ^0.0.2
|
specifier: ^0.0.2
|
||||||
version: 0.0.2(@kevisual/query@0.0.17(ws@8.18.0)(zod@3.24.2))
|
version: 0.0.2(@kevisual/query@0.0.17(ws@8.18.0)(zod@3.24.2))
|
||||||
'@kevisual/router':
|
'@kevisual/router':
|
||||||
specifier: 0.0.13
|
specifier: 0.0.14
|
||||||
version: 0.0.13
|
version: 0.0.14
|
||||||
'@kevisual/use-config':
|
'@kevisual/use-config':
|
||||||
specifier: ^1.0.15
|
specifier: ^1.0.15
|
||||||
version: 1.0.15(dotenv@16.4.7)
|
version: 1.0.15(dotenv@16.4.7)
|
||||||
@ -54,6 +54,12 @@ importers:
|
|||||||
specifier: ^6.37.7
|
specifier: ^6.37.7
|
||||||
version: 6.37.7(pg@8.13.3)
|
version: 6.37.7(pg@8.13.3)
|
||||||
devDependencies:
|
devDependencies:
|
||||||
|
'@kevisual/logger':
|
||||||
|
specifier: ^0.0.2
|
||||||
|
version: 0.0.2
|
||||||
|
'@kevisual/oss':
|
||||||
|
specifier: ^0.0.7
|
||||||
|
version: 0.0.7
|
||||||
'@rollup/plugin-commonjs':
|
'@rollup/plugin-commonjs':
|
||||||
specifier: ^28.0.3
|
specifier: ^28.0.3
|
||||||
version: 28.0.3(rollup@4.40.2)
|
version: 28.0.3(rollup@4.40.2)
|
||||||
@ -125,6 +131,12 @@ packages:
|
|||||||
'@kevisual/load@0.0.6':
|
'@kevisual/load@0.0.6':
|
||||||
resolution: {integrity: sha512-+3YTFehRcZ1haGel5DKYMUwmi5i6f2psyaPZlfkKU/cOXgkpwoG9/BEqPCnPjicKqqnksEpixVRkyHJ+5bjLVA==}
|
resolution: {integrity: sha512-+3YTFehRcZ1haGel5DKYMUwmi5i6f2psyaPZlfkKU/cOXgkpwoG9/BEqPCnPjicKqqnksEpixVRkyHJ+5bjLVA==}
|
||||||
|
|
||||||
|
'@kevisual/logger@0.0.2':
|
||||||
|
resolution: {integrity: sha512-4NVdNsOHmMRg+OuZPoNNdI3p7jRII7lMJHRar1IoBck7fFIV7YGMNQirrrjk07MHv+Eh+U+uUljjgEWbse92RA==}
|
||||||
|
|
||||||
|
'@kevisual/oss@0.0.7':
|
||||||
|
resolution: {integrity: sha512-saPN4A1CaGvSkFZzLE4zMsm+WwXi6Z97Yavz6koWFziuJIi/ay0793A4EDZ0iIpE9MMTRLYsuSQTUxDzsZV4Kg==}
|
||||||
|
|
||||||
'@kevisual/permission@0.0.1':
|
'@kevisual/permission@0.0.1':
|
||||||
resolution: {integrity: sha512-nSX2LzbPkU3YAMegbUFGU8tfmtFb7dcF5edqzm+gI6crcyCL1JzIB9HAYNEeEVIljLxuREwM/vVg9aFmF4cz9Q==}
|
resolution: {integrity: sha512-nSX2LzbPkU3YAMegbUFGU8tfmtFb7dcF5edqzm+gI6crcyCL1JzIB9HAYNEeEVIljLxuREwM/vVg9aFmF4cz9Q==}
|
||||||
|
|
||||||
@ -136,8 +148,8 @@ packages:
|
|||||||
'@kevisual/query@0.0.17':
|
'@kevisual/query@0.0.17':
|
||||||
resolution: {integrity: sha512-WMvWM+3pNlPKNhoxPX9fldMp1tOeJrkRM/tXA4bvOnftIoX2yeI4v0wTpbGJXES/bLlo7OC2kV8SeKF0K6dnxQ==}
|
resolution: {integrity: sha512-WMvWM+3pNlPKNhoxPX9fldMp1tOeJrkRM/tXA4bvOnftIoX2yeI4v0wTpbGJXES/bLlo7OC2kV8SeKF0K6dnxQ==}
|
||||||
|
|
||||||
'@kevisual/router@0.0.13':
|
'@kevisual/router@0.0.14':
|
||||||
resolution: {integrity: sha512-raji8aKXr0jigmJVOKBXb5gpstiAuyoIDy9m6SyPf4lRjCU3pspVI1bpscOUCBlaPICo6TLzPQxXhyTvvvtdWw==}
|
resolution: {integrity: sha512-eHOSD6gzs/Ed9DDTq9VCEM3uw3Wh1vPFlyPo91cEe2rA44t8oJm8g905qmwHVUEjbo5s/rA306ZW/ub06jlNlg==}
|
||||||
|
|
||||||
'@kevisual/use-config@1.0.15':
|
'@kevisual/use-config@1.0.15':
|
||||||
resolution: {integrity: sha512-bLWdGMOPHgIKV4qY3U18cLoOKmSBL72K1wL0MneyEsqj9jRXoc98OMMyQm2/BlBddFTL1olOfByRET2DvwmWAA==}
|
resolution: {integrity: sha512-bLWdGMOPHgIKV4qY3U18cLoOKmSBL72K1wL0MneyEsqj9jRXoc98OMMyQm2/BlBddFTL1olOfByRET2DvwmWAA==}
|
||||||
@ -1446,10 +1458,10 @@ snapshots:
|
|||||||
|
|
||||||
'@kevisual/auth@1.0.5': {}
|
'@kevisual/auth@1.0.5': {}
|
||||||
|
|
||||||
'@kevisual/code-center-module@0.0.18(@kevisual/auth@1.0.5)(@kevisual/router@0.0.13)(@kevisual/use-config@1.0.15(dotenv@16.4.7))(ioredis@5.6.1)(pg@8.13.3)(sequelize@6.37.7(pg@8.13.3))':
|
'@kevisual/code-center-module@0.0.18(@kevisual/auth@1.0.5)(@kevisual/router@0.0.14)(@kevisual/use-config@1.0.15(dotenv@16.4.7))(ioredis@5.6.1)(pg@8.13.3)(sequelize@6.37.7(pg@8.13.3))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@kevisual/auth': 1.0.5
|
'@kevisual/auth': 1.0.5
|
||||||
'@kevisual/router': 0.0.13
|
'@kevisual/router': 0.0.14
|
||||||
'@kevisual/use-config': 1.0.15(dotenv@16.4.7)
|
'@kevisual/use-config': 1.0.15(dotenv@16.4.7)
|
||||||
ioredis: 5.6.1
|
ioredis: 5.6.1
|
||||||
nanoid: 5.1.5
|
nanoid: 5.1.5
|
||||||
@ -1466,6 +1478,10 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
eventemitter3: 5.0.1
|
eventemitter3: 5.0.1
|
||||||
|
|
||||||
|
'@kevisual/logger@0.0.2': {}
|
||||||
|
|
||||||
|
'@kevisual/oss@0.0.7': {}
|
||||||
|
|
||||||
'@kevisual/permission@0.0.1': {}
|
'@kevisual/permission@0.0.1': {}
|
||||||
|
|
||||||
'@kevisual/query-config@0.0.2(@kevisual/query@0.0.17(ws@8.18.0)(zod@3.24.2))':
|
'@kevisual/query-config@0.0.2(@kevisual/query@0.0.17(ws@8.18.0)(zod@3.24.2))':
|
||||||
@ -1480,7 +1496,7 @@ snapshots:
|
|||||||
- ws
|
- ws
|
||||||
- zod
|
- zod
|
||||||
|
|
||||||
'@kevisual/router@0.0.13':
|
'@kevisual/router@0.0.14':
|
||||||
dependencies:
|
dependencies:
|
||||||
path-to-regexp: 8.2.0
|
path-to-regexp: 8.2.0
|
||||||
selfsigned: 2.4.1
|
selfsigned: 2.4.1
|
||||||
|
2
src/module/logger.ts
Normal file
2
src/module/logger.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
import { Logger } from '@kevisual/logger/node';
|
||||||
|
export const logger = new Logger();
|
@ -6,17 +6,13 @@ import { UserPermission, Permission } from '@kevisual/permission';
|
|||||||
import { getLoginUser } from '@/middleware/auth.ts';
|
import { getLoginUser } from '@/middleware/auth.ts';
|
||||||
import busboy from 'busboy';
|
import busboy from 'busboy';
|
||||||
import { getContentType } from '../get-content-type.ts';
|
import { getContentType } from '../get-content-type.ts';
|
||||||
|
import { OssBase } from '@kevisual/oss';
|
||||||
const getAiProxy = async (
|
import { parseSearchValue } from '@kevisual/router/browser';
|
||||||
req: IncomingMessage,
|
// import { logger } from '@/module/logger.ts';
|
||||||
res: ServerResponse,
|
const getAiProxy = async (req: IncomingMessage, res: ServerResponse, opts: ProxyOptions) => {
|
||||||
opts: {
|
|
||||||
createNotFoundPage: (msg?: string) => any;
|
|
||||||
},
|
|
||||||
) => {
|
|
||||||
const { createNotFoundPage } = opts;
|
const { createNotFoundPage } = opts;
|
||||||
const _u = new URL(req.url, 'http://localhost');
|
const _u = new URL(req.url, 'http://localhost');
|
||||||
|
const oss = opts.oss;
|
||||||
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');
|
||||||
@ -32,8 +28,8 @@ const getAiProxy = async (
|
|||||||
owner = user;
|
owner = user;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const stat = await minioClient.statObject(bucketName, objectName);
|
const stat = await oss.statObject(objectName);
|
||||||
if (stat.size === 0) {
|
if (!stat) {
|
||||||
createNotFoundPage('Invalid proxy url');
|
createNotFoundPage('Invalid proxy url');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -57,7 +53,7 @@ const getAiProxy = async (
|
|||||||
'Content-Length': contentLength,
|
'Content-Length': contentLength,
|
||||||
etag,
|
etag,
|
||||||
'last-modified': lastModified,
|
'last-modified': lastModified,
|
||||||
'file-name': fileName,
|
'x-file-name': fileName,
|
||||||
...filterMetaData,
|
...filterMetaData,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -90,11 +86,19 @@ export const getMetadata = (pathname: string) => {
|
|||||||
}
|
}
|
||||||
return meta;
|
return meta;
|
||||||
};
|
};
|
||||||
export const postProxy = async (req: IncomingMessage, res: ServerResponse, opts: { createNotFoundPage: (msg?: string) => any }) => {
|
|
||||||
|
export const postProxy = async (req: IncomingMessage, res: ServerResponse, opts: ProxyOptions) => {
|
||||||
const _u = new URL(req.url, 'http://localhost');
|
const _u = new URL(req.url, 'http://localhost');
|
||||||
|
|
||||||
const pathname = _u.pathname;
|
const pathname = _u.pathname;
|
||||||
|
const oss = opts.oss;
|
||||||
const params = _u.searchParams;
|
const params = _u.searchParams;
|
||||||
|
const force = !!params.get('force');
|
||||||
|
const hash = params.get('hash');
|
||||||
|
let meta = parseSearchValue(params.get('meta'), { decode: true });
|
||||||
|
if (!hash && !force) {
|
||||||
|
return opts?.createNotFoundPage?.('no hash');
|
||||||
|
}
|
||||||
let objectName = '';
|
let objectName = '';
|
||||||
let owner = '';
|
let owner = '';
|
||||||
const { user, app } = getUserFromRequest(req);
|
const { user, app } = getUserFromRequest(req);
|
||||||
@ -110,22 +114,48 @@ export const postProxy = async (req: IncomingMessage, res: ServerResponse, opts:
|
|||||||
if (loginUser?.tokenUser?.username !== owner) {
|
if (loginUser?.tokenUser?.username !== owner) {
|
||||||
return opts?.createNotFoundPage?.('no permission');
|
return opts?.createNotFoundPage?.('no permission');
|
||||||
}
|
}
|
||||||
const bb = busboy({ headers: req.headers });
|
const end = (data: any, message?: string, code = 200) => {
|
||||||
bb.on('file', async (name, file, info) => {
|
res.writeHead(code, { 'Content-Type': 'application/json' });
|
||||||
try {
|
res.end(JSON.stringify({ code: code, data: data, message: message || 'success' }));
|
||||||
await minioClient.putObject(bucketName, objectName, file, undefined, {
|
};
|
||||||
...getMetadata(pathname),
|
if (!force) {
|
||||||
|
const check = await oss.checkObjectHash(objectName, hash);
|
||||||
|
if (check) {
|
||||||
|
return end({ success: true, hash }, '文件已存在');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const bb = busboy({
|
||||||
|
headers: req.headers,
|
||||||
|
limits: {
|
||||||
|
fileSize: 100 * 1024 * 1024, // 100MB
|
||||||
|
files: 1,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
let fileProcessed = false;
|
||||||
|
bb.on('file', async (name, file, info) => {
|
||||||
|
fileProcessed = true;
|
||||||
|
try {
|
||||||
|
await oss.putObject(
|
||||||
|
objectName,
|
||||||
|
file,
|
||||||
|
{
|
||||||
|
...getMetadata(pathname),
|
||||||
|
...meta,
|
||||||
|
},
|
||||||
|
{ check: true, isStream: true },
|
||||||
|
);
|
||||||
end({ success: true, name, info }, '上传成功', 200);
|
end({ success: true, name, info }, '上传成功', 200);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
end({ error: error }, '上传失败', 500);
|
end({ error: error }, '上传失败', 500);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const end = (data: any, message?: string, code = 200) => {
|
|
||||||
res.writeHead(code, { 'Content-Type': 'application/json' });
|
bb.on('finish', () => {
|
||||||
res.end(JSON.stringify({ code: code, data: data, message: message || 'success' }));
|
// 只有当没有文件被处理时才执行end
|
||||||
};
|
if (!fileProcessed) {
|
||||||
bb.on('finish', end);
|
end({ success: false }, '没有接收到文件', 400);
|
||||||
|
}
|
||||||
|
});
|
||||||
bb.on('error', (err) => {
|
bb.on('error', (err) => {
|
||||||
console.error('Busboy 错误:', err);
|
console.error('Busboy 错误:', err);
|
||||||
end({ error: err }, '文件解析失败', 500);
|
end({ error: err }, '文件解析失败', 500);
|
||||||
@ -133,13 +163,15 @@ export const postProxy = async (req: IncomingMessage, res: ServerResponse, opts:
|
|||||||
|
|
||||||
req.pipe(bb);
|
req.pipe(bb);
|
||||||
};
|
};
|
||||||
export const aiProxy = async (
|
type ProxyOptions = {
|
||||||
req: IncomingMessage,
|
|
||||||
res: ServerResponse,
|
|
||||||
opts: {
|
|
||||||
createNotFoundPage: (msg?: string) => any;
|
createNotFoundPage: (msg?: string) => any;
|
||||||
},
|
oss?: OssBase;
|
||||||
) => {
|
};
|
||||||
|
export const aiProxy = async (req: IncomingMessage, res: ServerResponse, opts: ProxyOptions) => {
|
||||||
|
const oss = new OssBase({ bucketName, client: minioClient });
|
||||||
|
if (!opts.oss) {
|
||||||
|
opts.oss = oss;
|
||||||
|
}
|
||||||
if (req.method === 'POST') {
|
if (req.method === 'POST') {
|
||||||
return postProxy(req, res, opts);
|
return postProxy(req, res, opts);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user