This commit is contained in:
蒋小陌 2024-10-13 15:09:25 +08:00
parent db2c953ae6
commit d0b5151228

View File

@ -29,20 +29,17 @@ if (!fs.existsSync(cacheDir)) {
fs.mkdirSync(cacheDir);
}
// 定时清理过期缓存数据并更新请求
setInterval(async () => {
// 定时清理过期缓存数据
setInterval(() => {
const currentTime = Date.now();
for (const key in pathIndex) {
const { timestamp } = pathIndex[key];
// 24小时
if (currentTime - timestamp > 24 * 60 * 60 * 1000) {
if (currentTime - pathIndex[key].timestamp > 24 * 60 * 60 * 1000) {
delete pathIndex[key];
}
}
}, 1 * 60 * 60 * 1000); // 每隔 1 小时执行一次
}, 60 * 60 * 1000); // 每隔 1 小时执行一次
// 处理请求并返回数据
const server = http.createServer(async (req, res) => {
if (req.url === '/favicon.ico') {
res.writeHead(204);
@ -50,6 +47,21 @@ const server = http.createServer(async (req, res) => {
return;
}
// 返回 endpoint, 缓存目录, 缓存数量, 用于监听服务是否正常运行
if (req.url === '/endpoint') {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
code: 200,
data: {
api: apiEndpoint,
port: port,
cacheDir: cacheDir,
pathIndexCount: Object.keys(pathIndex).length,
}
}));
return;
}
const parsedUrl = url.parse(req.url, true);
const reqPath = parsedUrl.pathname;
const sign = parsedUrl.query.sign || '';
@ -83,7 +95,6 @@ const server = http.createServer(async (req, res) => {
// 修改 pathIndex 记录时,添加时间戳
pathIndex[uniqidhex] = { uniqid: data.uniqid, timestamp: Date.now() };
cacheMetaFile = pathModule.join(cacheDir, `${data.uniqid}.meta`);
cacheContentFile = pathModule.join(cacheDir, `${data.uniqid}.content`);
tempCacheContentFile = pathModule.join(cacheDir, `${data.uniqid}_${crypto.randomBytes(16).toString('hex')}.temp`);
@ -94,20 +105,21 @@ const server = http.createServer(async (req, res) => {
// 如果内容缓存存在, 则直接调用
if (fs.existsSync(cacheContentFile)) {
serveFromCache(cacheMetaFile, cacheContentFile, res);
return;
}
} else {
fetchAndServe(data, tempCacheContentFile, cacheContentFile, res);
}
} else {
res.writeHead(502, { 'Content-Type': 'text/plain' });
res.end(apiData.message || 'Bad Gateway');
}
} catch (error) {
res.writeHead(502, { 'Content-Type': 'text/plain' });
res.end('Bad Gateway: Failed to decode JSON' + error);
res.end('Bad Gateway: Failed to decode JSON ' + error);
}
}
});
// 检查缓存是否有效
const isCacheValid = (cacheMetaFile, cacheContentFile) => {
if (!fs.existsSync(cacheMetaFile) || !fs.existsSync(cacheContentFile)) return false;
@ -115,6 +127,7 @@ const isCacheValid = (cacheMetaFile, cacheContentFile) => {
return cacheData.expiration > Date.now();
};
// 从 API 获取数据
const fetchApiData = (reqPath, sign) => {
return new Promise((resolve, reject) => {
const postData = querystring.stringify({ path: reqPath, sign });
@ -146,6 +159,7 @@ const fetchApiData = (reqPath, sign) => {
});
};
// 从真实 URL 获取数据并写入缓存
const fetchAndServe = (data, tempCacheContentFile, cacheContentFile, res) => {
https.get(data.realUrl, { timeout: requestTimeout * 10 }, (realRes) => {
const cacheStream = fs.createWriteStream(tempCacheContentFile, { flags: 'w' });
@ -188,6 +202,7 @@ const fetchAndServe = (data, tempCacheContentFile, cacheContentFile, res) => {
});
};
// 从缓存中读取数据并返回
const serveFromCache = (cacheMetaFile, cacheContentFile, res) => {
const cacheData = JSON.parse(fs.readFileSync(cacheMetaFile, 'utf8'));
const readStream = fs.createReadStream(cacheContentFile);
@ -217,6 +232,7 @@ const serveFromCache = (cacheMetaFile, cacheContentFile, res) => {
});
};
// 处理响应错误
const handleResponseError = (res, tempCacheContentFile, realUrl) => {
if (!res.headersSent) {
res.writeHead(502, { 'Content-Type': 'text/plain' });
@ -227,6 +243,7 @@ const handleResponseError = (res, tempCacheContentFile, realUrl) => {
}
};
// 处理缓存读取错误
const handleCacheReadError = (res) => {
if (!res.headersSent) {
res.writeHead(500, { 'Content-Type': 'text/plain' });
@ -234,11 +251,12 @@ const handleCacheReadError = (res) => {
}
};
// 启动服务器
server.listen(port, () => {
console.log(`Proxy server is running on http://localhost:${port}`);
});
// Graceful shutdown
// 处理 SIGINT 信号Ctrl+C
process.on('SIGINT', () => {
console.log('Received SIGINT. Shutting down gracefully...');
server.close(() => {