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