83 lines
2.5 KiB
TypeScript

import http from 'http';
import https from 'https';
import { ProxyInfo } from './proxy.ts';
export const defaultApiProxy = [
{
path: '/api/router',
target: 'https://kevisual.xiongxiao.me',
},
{
path: '/v1',
target: 'https://kevisual.xiongxiao.me',
},
];
/**
* 创建api代理
* @param api
* @param paths ['/api/router', '/v1' ]
* @returns
*/
export const createApiProxy = (api: string, paths: string[] = ['/api/router', '/v1', '/resources']) => {
const pathList = paths.map((item) => {
return {
path: item,
target: new URL(api).origin,
};
});
return pathList;
};
export const apiProxy = (req: http.IncomingMessage, res: http.ServerResponse, proxyApi: ProxyInfo) => {
const _u = new URL(req.url, `${proxyApi.target}`);
console.log('proxyApi', req.url, _u.href);
// 设置代理请求的目标 URL 和请求头
let header: any = {};
if (req.headers?.['Authorization'] && !req.headers?.['authorization']) {
header.authorization = req.headers['Authorization'];
}
// 提取req的headers中的非HOST的header
const headers = Object.keys(req.headers).filter((item) => item && item.toLowerCase() !== 'host');
headers.forEach((item) => {
if (item.toLowerCase() === 'origin') {
header.origin = new URL(proxyApi.target).origin;
return;
}
if (item.toLowerCase() === 'referer') {
header.referer = new URL(req.url, proxyApi.target).href;
return;
}
header[item] = req.headers[item];
});
const options = {
host: _u.hostname,
path: req.url,
method: req.method,
headers: {
...header,
},
};
console.log('options', JSON.stringify(options, null, 2));
if (_u.port) {
// @ts-ignore
options.port = _u.port;
}
const httpProxy = _u.protocol === 'https:' ? https : http;
// 创建代理请求
const proxyReq = httpProxy.request(options, (proxyRes) => {
// 将代理服务器的响应头和状态码返回给客户端
res.writeHead(proxyRes.statusCode, proxyRes.headers);
// 将代理响应流写入客户端响应
proxyRes.pipe(res, { end: true });
});
// 处理代理请求的错误事件
proxyReq.on('error', (err) => {
console.error(`Proxy request error: ${err.message}`);
res.writeHead(500, { 'Content-Type': 'text/plain' });
res.write(`Proxy request error: ${err.message}`);
});
// 处理 POST 请求的请求体(传递数据到目标服务器),end:true 表示当请求体结束时,关闭请求
req.pipe(proxyReq, { end: true });
return;
};