fix: 配置修改,添加socket代理
This commit is contained in:
		@@ -11,6 +11,17 @@ type ConfigType = {
 | 
			
		||||
    path?: string;
 | 
			
		||||
    port?: number;
 | 
			
		||||
  };
 | 
			
		||||
  apiList: {
 | 
			
		||||
    path: string;
 | 
			
		||||
    /**
 | 
			
		||||
     * url或者相对路径
 | 
			
		||||
     */
 | 
			
		||||
    target: string;
 | 
			
		||||
    /**
 | 
			
		||||
     * 类型
 | 
			
		||||
     */
 | 
			
		||||
    type?: 'static' | 'dynamic' | 'minio';
 | 
			
		||||
  }[];
 | 
			
		||||
  proxy: {
 | 
			
		||||
    port?: number;
 | 
			
		||||
    /**
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,8 @@ import path from 'path';
 | 
			
		||||
import fs from 'fs';
 | 
			
		||||
import { getContentType } from './get-content-type.ts';
 | 
			
		||||
import { createRefreshHtml } from './html/create-refresh-html.ts';
 | 
			
		||||
import { fileProxy } from './proxy/file-proxy.ts';
 | 
			
		||||
import net from 'net';
 | 
			
		||||
 | 
			
		||||
const api = config?.api || { host: 'kevisual.xiongxiao.me', path: '/api/router' };
 | 
			
		||||
const domain = config?.proxy?.domain || 'kevisual.xiongxiao.me';
 | 
			
		||||
@@ -20,11 +22,18 @@ export const handleRequest = async (req: http.IncomingMessage, res: http.ServerR
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  if (req.url.startsWith('/api/proxy')) {
 | 
			
		||||
    // 已经代理过了
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  if (req.url.startsWith('/api')) {
 | 
			
		||||
    // 代理到 http://codeflow.xiongxiao.me/api
 | 
			
		||||
    const _u = new URL(req.url, `http://${api.host}`);
 | 
			
		||||
  console.log('req', req.url, 'len', config?.apiList?.length);
 | 
			
		||||
  const proxyApiList = config?.apiList || [];
 | 
			
		||||
  const proxyApi = proxyApiList.find((item) => req.url.startsWith(item.path));
 | 
			
		||||
  if (proxyApi && proxyApi?.type === 'static') {
 | 
			
		||||
    return fileProxy(req, res, proxyApi);
 | 
			
		||||
  }
 | 
			
		||||
  if (proxyApi) {
 | 
			
		||||
    const _u = new URL(req.url, `${proxyApi.target}`);
 | 
			
		||||
    console.log('proxyApi', req.url, _u.href);
 | 
			
		||||
    // 设置代理请求的目标 URL 和请求头
 | 
			
		||||
    let header: any = {};
 | 
			
		||||
    if (req.headers?.['Authorization']) {
 | 
			
		||||
@@ -32,9 +41,11 @@ export const handleRequest = async (req: http.IncomingMessage, res: http.ServerR
 | 
			
		||||
    } else if (req.headers?.['authorization']) {
 | 
			
		||||
      header.authorization = req.headers['authorization'];
 | 
			
		||||
    }
 | 
			
		||||
    if (req.headers?.['Content-Type']) {
 | 
			
		||||
      header['Content-Type'] = req.headers?.['Content-Type'];
 | 
			
		||||
    }
 | 
			
		||||
    // 提取req的headers中的非HOST的header
 | 
			
		||||
    const headers = Object.keys(req.headers).filter((item) => item && item.toLowerCase() !== 'host');
 | 
			
		||||
    headers.forEach((item) => {
 | 
			
		||||
      header[item] = req.headers[item];
 | 
			
		||||
    });
 | 
			
		||||
    const options = {
 | 
			
		||||
      host: _u.hostname,
 | 
			
		||||
      path: req.url,
 | 
			
		||||
@@ -64,7 +75,7 @@ export const handleRequest = async (req: http.IncomingMessage, res: http.ServerR
 | 
			
		||||
    req.pipe(proxyReq, { end: true });
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  if (req.url.startsWith('/api')) {
 | 
			
		||||
  if (req.url.startsWith('/api') || req.url.startsWith('/v1')) {
 | 
			
		||||
    res.end('not catch api');
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
@@ -244,3 +255,4 @@ export const handleRequest = async (req: http.IncomingMessage, res: http.ServerR
 | 
			
		||||
    console.error('getFile error', error);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										24
									
								
								src/module/minio.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/module/minio.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
			
		||||
import { Client, ClientOptions } from 'minio';
 | 
			
		||||
import { useConfig } from '@kevisual/use-config';
 | 
			
		||||
 | 
			
		||||
type MinioConfig = {
 | 
			
		||||
  minio: ClientOptions & { bucketName: string };
 | 
			
		||||
};
 | 
			
		||||
const config = useConfig<MinioConfig>();
 | 
			
		||||
 | 
			
		||||
const { bucketName, ...minioRest } = config.minio;
 | 
			
		||||
export const minioClient = new Client(minioRest);
 | 
			
		||||
export { bucketName };
 | 
			
		||||
if (!minioClient) {
 | 
			
		||||
  throw new Error('Minio client not initialized');
 | 
			
		||||
}
 | 
			
		||||
// 验证权限
 | 
			
		||||
// (async () => {
 | 
			
		||||
//   const bucketExists = await minioClient.bucketExists(bucketName);
 | 
			
		||||
//   if (!bucketExists) {
 | 
			
		||||
//     await minioClient.makeBucket(bucketName);
 | 
			
		||||
//   }
 | 
			
		||||
//   const res = await minioClient.putObject(bucketName, 'private/test/a.b', 'test');
 | 
			
		||||
//   console.log('minio putObject', res);
 | 
			
		||||
 | 
			
		||||
// })();
 | 
			
		||||
							
								
								
									
										26
									
								
								src/module/proxy/file-proxy.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/module/proxy/file-proxy.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
			
		||||
import http from 'http';
 | 
			
		||||
import send from 'send';
 | 
			
		||||
import fs from 'fs';
 | 
			
		||||
import { fileIsExist } from '@kevisual/use-config';
 | 
			
		||||
import path from 'path';
 | 
			
		||||
export type ProxyInfo = {
 | 
			
		||||
  path?: string;
 | 
			
		||||
  target: string;
 | 
			
		||||
  type?: 'static' | 'dynamic' | 'minio';
 | 
			
		||||
};
 | 
			
		||||
export const fileProxy = (req: http.IncomingMessage, res: http.ServerResponse, proxyApi: ProxyInfo) => {
 | 
			
		||||
  // url开头的文件
 | 
			
		||||
  const url = new URL(req.url, 'http://localhost');
 | 
			
		||||
  const pathname = url.pathname;
 | 
			
		||||
  // 检测文件是否存在,如果文件不存在,则返回404
 | 
			
		||||
  const filePath = path.join(process.cwd(), proxyApi.target, pathname);
 | 
			
		||||
  if (!fileIsExist(filePath)) {
 | 
			
		||||
    res.statusCode = 404;
 | 
			
		||||
    res.end('Not Found File');
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  const file = send(req, pathname, {
 | 
			
		||||
    root: proxyApi.target,
 | 
			
		||||
  });
 | 
			
		||||
  file.pipe(res);
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										24
									
								
								src/module/proxy/minio-proxy.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/module/proxy/minio-proxy.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
			
		||||
import http from 'http';
 | 
			
		||||
import { minioClient } from '../minio.ts';
 | 
			
		||||
export type ProxyInfo = {
 | 
			
		||||
  path?: string;
 | 
			
		||||
  target: string;
 | 
			
		||||
  type?: 'static' | 'dynamic' | 'minio';
 | 
			
		||||
};
 | 
			
		||||
export const minioProxy = async (req: http.IncomingMessage, res: http.ServerResponse, proxyApi: ProxyInfo) => {
 | 
			
		||||
  try {
 | 
			
		||||
    const requestUrl = new URL(req.url, 'http://localhost');
 | 
			
		||||
    const objectPath = requestUrl.pathname;
 | 
			
		||||
    const bucketName = proxyApi.target;
 | 
			
		||||
    let objectName = objectPath.slice(1);
 | 
			
		||||
    if (objectName.startsWith(bucketName)) {
 | 
			
		||||
      objectName = objectName.slice(bucketName.length);
 | 
			
		||||
    }
 | 
			
		||||
    const objectStream = await minioClient.getObject(bucketName, objectName);
 | 
			
		||||
    objectStream.pipe(res);
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
    console.error('Error fetching object from MinIO:', error);
 | 
			
		||||
    res.statusCode = 500;
 | 
			
		||||
    res.end('Internal Server Error');
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
		Reference in New Issue
	
	Block a user