update
This commit is contained in:
@@ -197,6 +197,7 @@ export const postProxy = async (req: IncomingMessage, res: ServerResponse, opts:
|
|||||||
fileSize: 100 * 1024 * 1024, // 100MB
|
fileSize: 100 * 1024 * 1024, // 100MB
|
||||||
files: 1,
|
files: 1,
|
||||||
},
|
},
|
||||||
|
defCharset: 'utf-8',
|
||||||
});
|
});
|
||||||
let fileProcessed = false;
|
let fileProcessed = false;
|
||||||
bb.on('file', async (name, file, info) => {
|
bb.on('file', async (name, file, info) => {
|
||||||
|
|||||||
@@ -58,7 +58,9 @@ export class WsProxyManager {
|
|||||||
value.ws.close();
|
value.ws.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log('WsProxyManager register', id);
|
const [username, appId] = id.split('-');
|
||||||
|
const url = new URL(`/${username}/v1/${appId}`, 'https://kevisual.cn/');
|
||||||
|
console.log('WsProxyManager register', id, '访问地址', url.toString());
|
||||||
const value = new WsMessage({ ws: opts?.ws, user: opts?.user });
|
const value = new WsMessage({ ws: opts?.ws, user: opts?.user });
|
||||||
this.wssMap.set(id, value);
|
this.wssMap.set(id, value);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,12 +10,16 @@ type ProxyOptions = {
|
|||||||
};
|
};
|
||||||
export const UserV1Proxy = async (req: IncomingMessage, res: ServerResponse, opts?: ProxyOptions) => {
|
export const UserV1Proxy = async (req: IncomingMessage, res: ServerResponse, opts?: ProxyOptions) => {
|
||||||
const { url } = req;
|
const { url } = req;
|
||||||
const { pathname } = new URL(url || '', `http://localhost`);
|
const _url = new URL(url || '', `http://localhost`);
|
||||||
|
const { pathname, searchParams } = _url;
|
||||||
let [user, app, userAppKey] = pathname.split('/').slice(1);
|
let [user, app, userAppKey] = pathname.split('/').slice(1);
|
||||||
if (!user || !app || !userAppKey) {
|
if (!user || !app || !userAppKey) {
|
||||||
opts?.createNotFoundPage?.('应用未找到');
|
opts?.createNotFoundPage?.('应用未找到');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (!userAppKey.includes('-')) {
|
||||||
|
userAppKey = user + '-' + userAppKey;
|
||||||
|
}
|
||||||
|
|
||||||
const data = await App.handleRequest(req, res);
|
const data = await App.handleRequest(req, res);
|
||||||
const loginUser = await getLoginUser(req);
|
const loginUser = await getLoginUser(req);
|
||||||
@@ -43,6 +47,14 @@ export const UserV1Proxy = async (req: IncomingMessage, res: ServerResponse, opt
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
const path = searchParams.get('path');
|
||||||
|
if (!path) {
|
||||||
|
// 显示前端页面
|
||||||
|
const html = fetch('https://kevisual.cn/root/router-studio/index.html').then(res => res.text());
|
||||||
|
res.writeHead(200, { 'Content-Type': 'text/html' });
|
||||||
|
res.end(await html);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
const value = await client.sendData(data);
|
const value = await client.sendData(data);
|
||||||
if (value) {
|
if (value) {
|
||||||
res.writeHead(200, { 'Content-Type': 'application/json' });
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ router.post('/api/micro-app/upload', async (req, res) => {
|
|||||||
if (!tokenUser) return;
|
if (!tokenUser) return;
|
||||||
|
|
||||||
// 使用 busboy 解析 multipart/form-data
|
// 使用 busboy 解析 multipart/form-data
|
||||||
const busboy = Busboy({ headers: req.headers, preservePath: true });
|
const busboy = Busboy({ headers: req.headers, preservePath: true, defCharset: 'utf-8' });
|
||||||
const fields: any = {};
|
const fields: any = {};
|
||||||
let file: any = null;
|
let file: any = null;
|
||||||
let filePromise: Promise<void> | null = null;
|
let filePromise: Promise<void> | null = null;
|
||||||
@@ -33,6 +33,8 @@ router.post('/api/micro-app/upload', async (req, res) => {
|
|||||||
|
|
||||||
busboy.on('file', (fieldname, fileStream, info) => {
|
busboy.on('file', (fieldname, fileStream, info) => {
|
||||||
const { filename, encoding, mimeType } = info;
|
const { filename, encoding, mimeType } = info;
|
||||||
|
// 处理 UTF-8 文件名编码
|
||||||
|
const decodedFilename = typeof filename === 'string' ? Buffer.from(filename, 'latin1').toString('utf8') : filename;
|
||||||
const tempPath = path.join(cacheFilePath, `${Date.now()}-${Math.random().toString(36).substring(7)}`);
|
const tempPath = path.join(cacheFilePath, `${Date.now()}-${Math.random().toString(36).substring(7)}`);
|
||||||
const writeStream = createWriteStream(tempPath);
|
const writeStream = createWriteStream(tempPath);
|
||||||
const hash = crypto.createHash('md5');
|
const hash = crypto.createHash('md5');
|
||||||
@@ -59,7 +61,7 @@ router.post('/api/micro-app/upload', async (req, res) => {
|
|||||||
writeStream.on('finish', () => {
|
writeStream.on('finish', () => {
|
||||||
file = {
|
file = {
|
||||||
filepath: tempPath,
|
filepath: tempPath,
|
||||||
originalFilename: filename,
|
originalFilename: decodedFilename,
|
||||||
mimetype: mimeType,
|
mimetype: mimeType,
|
||||||
hash: hash.digest('hex'),
|
hash: hash.digest('hex'),
|
||||||
size: size,
|
size: size,
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ router.post('/api/app/upload', async (req, res) => {
|
|||||||
if (!tokenUser) return;
|
if (!tokenUser) return;
|
||||||
|
|
||||||
// 使用 busboy 解析 multipart/form-data
|
// 使用 busboy 解析 multipart/form-data
|
||||||
const busboy = Busboy({ headers: req.headers, preservePath: true });
|
const busboy = Busboy({ headers: req.headers, preservePath: true, defCharset: 'utf-8' });
|
||||||
const fields: any = {};
|
const fields: any = {};
|
||||||
const files: any = [];
|
const files: any = [];
|
||||||
const filePromises: Promise<void>[] = [];
|
const filePromises: Promise<void>[] = [];
|
||||||
@@ -41,6 +41,8 @@ router.post('/api/app/upload', async (req, res) => {
|
|||||||
|
|
||||||
busboy.on('file', (fieldname, fileStream, info) => {
|
busboy.on('file', (fieldname, fileStream, info) => {
|
||||||
const { filename, encoding, mimeType } = info;
|
const { filename, encoding, mimeType } = info;
|
||||||
|
// 处理 UTF-8 文件名编码
|
||||||
|
const decodedFilename = typeof filename === 'string' ? Buffer.from(filename, 'latin1').toString('utf8') : filename;
|
||||||
const tempPath = path.join(cacheFilePath, `${Date.now()}-${Math.random().toString(36).substring(7)}`);
|
const tempPath = path.join(cacheFilePath, `${Date.now()}-${Math.random().toString(36).substring(7)}`);
|
||||||
const writeStream = createWriteStream(tempPath);
|
const writeStream = createWriteStream(tempPath);
|
||||||
|
|
||||||
@@ -63,7 +65,7 @@ router.post('/api/app/upload', async (req, res) => {
|
|||||||
writeStream.on('finish', () => {
|
writeStream.on('finish', () => {
|
||||||
files.push({
|
files.push({
|
||||||
filepath: tempPath,
|
filepath: tempPath,
|
||||||
originalFilename: filename,
|
originalFilename: decodedFilename,
|
||||||
mimetype: mimeType,
|
mimetype: mimeType,
|
||||||
});
|
});
|
||||||
resolve();
|
resolve();
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ router.post('/api/s1/resources/upload/chunk', async (req, res) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 使用 busboy 解析 multipart/form-data
|
// 使用 busboy 解析 multipart/form-data
|
||||||
const busboy = Busboy({ headers: req.headers, preservePath: true });
|
const busboy = Busboy({ headers: req.headers, preservePath: true, defCharset: 'utf-8' });
|
||||||
const fields: any = {};
|
const fields: any = {};
|
||||||
let file: any = null;
|
let file: any = null;
|
||||||
let tempPath = '';
|
let tempPath = '';
|
||||||
@@ -47,6 +47,8 @@ router.post('/api/s1/resources/upload/chunk', async (req, res) => {
|
|||||||
|
|
||||||
busboy.on('file', (fieldname, fileStream, info) => {
|
busboy.on('file', (fieldname, fileStream, info) => {
|
||||||
const { filename, encoding, mimeType } = info;
|
const { filename, encoding, mimeType } = info;
|
||||||
|
// 处理 UTF-8 文件名编码
|
||||||
|
const decodedFilename = typeof filename === 'string' ? Buffer.from(filename, 'latin1').toString('utf8') : filename;
|
||||||
tempPath = path.join(cacheFilePath, `${Date.now()}-${Math.random().toString(36).substring(7)}`);
|
tempPath = path.join(cacheFilePath, `${Date.now()}-${Math.random().toString(36).substring(7)}`);
|
||||||
const writeStream = createWriteStream(tempPath);
|
const writeStream = createWriteStream(tempPath);
|
||||||
|
|
||||||
@@ -56,7 +58,7 @@ router.post('/api/s1/resources/upload/chunk', async (req, res) => {
|
|||||||
writeStream.on('finish', () => {
|
writeStream.on('finish', () => {
|
||||||
file = {
|
file = {
|
||||||
filepath: tempPath,
|
filepath: tempPath,
|
||||||
originalFilename: filename,
|
originalFilename: decodedFilename,
|
||||||
mimetype: mimeType,
|
mimetype: mimeType,
|
||||||
};
|
};
|
||||||
resolve();
|
resolve();
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ router.post('/api/s1/resources/upload', async (req, res) => {
|
|||||||
const meta = parseIfJson(url.searchParams.get('meta'));
|
const meta = parseIfJson(url.searchParams.get('meta'));
|
||||||
const noCheckAppFiles = !!url.searchParams.get('noCheckAppFiles');
|
const noCheckAppFiles = !!url.searchParams.get('noCheckAppFiles');
|
||||||
// 使用 busboy 解析 multipart/form-data
|
// 使用 busboy 解析 multipart/form-data
|
||||||
const busboy = Busboy({ headers: req.headers, preservePath: true });
|
const busboy = Busboy({ headers: req.headers, preservePath: true, defCharset: 'utf-8' });
|
||||||
const fields: any = {};
|
const fields: any = {};
|
||||||
const files: any[] = [];
|
const files: any[] = [];
|
||||||
const filePromises: Promise<void>[] = [];
|
const filePromises: Promise<void>[] = [];
|
||||||
@@ -119,6 +119,8 @@ router.post('/api/s1/resources/upload', async (req, res) => {
|
|||||||
|
|
||||||
busboy.on('file', (fieldname, fileStream, info) => {
|
busboy.on('file', (fieldname, fileStream, info) => {
|
||||||
const { filename, encoding, mimeType } = info;
|
const { filename, encoding, mimeType } = info;
|
||||||
|
// 处理 UTF-8 文件名编码(busboy 可能返回 Latin-1 编码的缓冲区)
|
||||||
|
const decodedFilename = typeof filename === 'string' ? Buffer.from(filename, 'latin1').toString('utf8') : filename;
|
||||||
const tempPath = path.join(cacheFilePath, `${Date.now()}-${Math.random().toString(36).substring(7)}`);
|
const tempPath = path.join(cacheFilePath, `${Date.now()}-${Math.random().toString(36).substring(7)}`);
|
||||||
const writeStream = createWriteStream(tempPath);
|
const writeStream = createWriteStream(tempPath);
|
||||||
const filePromise = new Promise<void>((resolve, reject) => {
|
const filePromise = new Promise<void>((resolve, reject) => {
|
||||||
@@ -140,7 +142,7 @@ router.post('/api/s1/resources/upload', async (req, res) => {
|
|||||||
writeStream.on('finish', () => {
|
writeStream.on('finish', () => {
|
||||||
files.push({
|
files.push({
|
||||||
filepath: tempPath,
|
filepath: tempPath,
|
||||||
originalFilename: filename,
|
originalFilename: decodedFilename,
|
||||||
mimetype: mimeType,
|
mimetype: mimeType,
|
||||||
});
|
});
|
||||||
resolve();
|
resolve();
|
||||||
|
|||||||
Reference in New Issue
Block a user