This commit is contained in:
蒋小陌 2024-09-27 23:09:57 +08:00
parent 15a9a009a3
commit 6b33982a55

View File

@ -37,8 +37,6 @@ const server = http.createServer(async (req, res) => {
const parsedUrl = url.parse(req.url, true);
const reqPath = parsedUrl.pathname;
const sign = parsedUrl.query.sign || '';
// 只要reqPath的文件名不要路径
const reqName = parsedUrl.pathname.split('/').pop();
const cacheMetaFile = path.join(cacheDir, `${reqName.replace(/\//g, '_')}.meta`);
const cacheContentFile = path.join(cacheDir, `${reqName.replace(/\//g, '_')}.content`);
@ -63,7 +61,6 @@ const server = http.createServer(async (req, res) => {
fs.writeFileSync(cacheMetaFile, JSON.stringify(data));
}
// 如果 cacheContentFile 存在 直接调用它
if (fs.existsSync(cacheContentFile)) {
serveFromCache(cacheMetaFile, cacheContentFile, res);
return;
@ -120,31 +117,36 @@ const fetchApiData = (reqPath, sign) => {
const fetchAndServe = (data, tempCacheContentFile, cacheContentFile, res) => {
https.get(data.realUrl, { timeout: requestTimeout * 10 }, (realRes) => {
// 创建临时缓存文件流
const cacheStream = fs.createWriteStream(tempCacheContentFile, { flags: 'w' });
// 通过 data.path 判断是否是视频.mp4
const isVideo = data.path.includes('.mp4');
data.headers['content-length'] = realRes.headers['content-length'];
res.writeHead(realRes.statusCode, {
...data.headers,
'Content-Type': isVideo ? 'video/mp4' : 'application/octet-stream',
'Cloud-Type': data.cloudtype,
'Cloud-Expiration': data.expiration,
// 添加缓存, 浏览器缓存不再重复请求
'Content-Type': isVideo ? 'video/mp4' : 'application/octet-stream',
'ETag': data.uniqid || '',
'Cache-Control': 'public, max-age=31536000',
'Expires': new Date(Date.now() + 31536000000).toUTCString(),
'Accept-Ranges': 'bytes',
'Connection': 'keep-alive',
'Date': new Date().toUTCString(),
'Last-Modified': new Date().toUTCString(),
'ETag': data.uniqid || ''
});
realRes.pipe(cacheStream);
realRes.pipe(res);
realRes.on('end', () => {
// 下载完成后,将临时文件重命名为最终缓存文件
fs.renameSync(tempCacheContentFile, cacheContentFile);
cacheStream.end();
if (fs.existsSync(tempCacheContentFile)) {
try {
fs.renameSync(tempCacheContentFile, cacheContentFile);
} catch (err) {
console.error(`Error renaming file: ${err}`);
}
}
});
realRes.on('error', (e) => {
@ -152,33 +154,41 @@ const fetchAndServe = (data, tempCacheContentFile, cacheContentFile, res) => {
res.writeHead(502, { 'Content-Type': 'text/plain' });
res.end(`Bad Gateway: ${data.realUrl}`);
}
fs.unlinkSync(tempCacheContentFile); // 删除临时文件
if (fs.existsSync(tempCacheContentFile)) {
fs.unlinkSync(tempCacheContentFile);
}
});
}).on('error', (e) => {
if (!res.headersSent) {
res.writeHead(502, { 'Content-Type': 'text/plain' });
res.end(`Bad Gateway: ${data.realUrl}`);
}
fs.unlinkSync(tempCacheContentFile); // 删除临时文件
if (fs.existsSync(tempCacheContentFile)) {
fs.unlinkSync(tempCacheContentFile);
}
});
};
const serveFromCache = (cacheMetaFile, cacheContentFile, res) => {
const cacheData = JSON.parse(fs.readFileSync(cacheMetaFile, 'utf8'));
const readStream = fs.createReadStream(cacheContentFile);
// 判断是否是视频
const isVideo = cacheData.path.includes('.mp4');
cacheData.headers['content-length'] = fs.statSync(cacheContentFile).size;
readStream.on('open', () => {
res.writeHead(200, {
...cacheData.headers,
'Content-Type': isVideo ? 'video/mp4' : 'application/octet-stream',
'Cloud-Type': cacheData.cloudtype,
'Cloud-Expiration': cacheData.expiration,
// 添加缓存, 浏览器缓存不再重复请求
'Content-Type': isVideo ? 'video/mp4' : 'application/octet-stream',
'ETag': cacheData.uniqid || '',
'Cache-Control': 'public, max-age=31536000',
'Expires': new Date(Date.now() + 31536000000).toUTCString(),
'Accept-Ranges': 'bytes',
'Connection': 'keep-alive',
'Date': new Date().toUTCString(),
'Last-Modified': new Date().toUTCString(),
'ETag': cacheData.uniqid || ''
});
readStream.pipe(res);
});
@ -203,7 +213,6 @@ process.on('SIGINT', () => {
process.exit(0);
});
// Force shutdown after 10 seconds if not closed
setTimeout(() => {
console.error('Forcing shutdown...');
process.exit(1);