From 6ea61759fd5cd262029af2e084cea90de4dac76c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=92=8B=E5=B0=8F=E9=99=8C?= Date: Tue, 24 Sep 2024 22:55:41 +0800 Subject: [PATCH] 111 --- oss.js | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 oss.js diff --git a/oss.js b/oss.js new file mode 100644 index 0000000..b0f999d --- /dev/null +++ b/oss.js @@ -0,0 +1,109 @@ +const http = require('http'); +const https = require('https'); +const fs = require('fs'); +const path = require('path'); + +const PORT = 3000; +const CACHE_DIR = path.join(__dirname, '.cache'); +const CACHE_EXPIRY = 30 * 24 * 60 * 60 * 1000; // 30 days in milliseconds +const CLEAN_INTERVAL = 24 * 60 * 60 * 1000; // 1 day in milliseconds + +// Ensure the cache directory exists +if (!fs.existsSync(CACHE_DIR)) { + fs.mkdirSync(CACHE_DIR); +} + +// Helper function to get cache file path +const getCacheFilePath = (requestUrl) => { + const sanitizedUrl = requestUrl.replace(/[^a-z0-9]/gi, '_').toLowerCase(); + return path.join(CACHE_DIR, sanitizedUrl); +}; + +// Function to clean up expired cache files +const cleanUpCache = () => { + fs.readdir(CACHE_DIR, (err, files) => { + if (err) { + console.error('Error reading cache directory:', err); + return; + } + + const now = Date.now(); + + files.forEach(file => { + const filePath = path.join(CACHE_DIR, file); + + fs.stat(filePath, (err, stats) => { + if (err) { + console.error('Error getting file stats:', err); + return; + } + + if (now - stats.mtimeMs > CACHE_EXPIRY) { + fs.unlink(filePath, (err) => { + if (err) { + console.error('Error deleting file:', err); + } + }); + } + }); + }); + }); +}; + +// Schedule cache clean-up at regular intervals +setInterval(cleanUpCache, CLEAN_INTERVAL); + +// Function to handle proxying and caching +const handleRequest = (req, res) => { + const targetUrl = `https://oss.x-php.com${req.url}`; + const cacheFilePath = getCacheFilePath(targetUrl); + + // Check if the cache file exists and is still valid + if (fs.existsSync(cacheFilePath)) { + const stats = fs.statSync(cacheFilePath); + const now = Date.now(); + + if (now - stats.mtimeMs < CACHE_EXPIRY) { + // Serve from cache + const cachedData = JSON.parse(fs.readFileSync(cacheFilePath, 'utf8')); + res.writeHead(cachedData.statusCode, cachedData.headers); + res.end(Buffer.from(cachedData.body, 'base64')); + return; + } + } + + // Fetch from the target URL + https.get(targetUrl, (proxyRes) => { + let data = []; + + proxyRes.on('data', (chunk) => { + data.push(chunk); + }); + + proxyRes.on('end', () => { + const responseData = Buffer.concat(data); + + // Save the response to cache + const cacheData = { + statusCode: proxyRes.statusCode, + headers: proxyRes.headers, + body: responseData.toString('base64') + }; + fs.writeFileSync(cacheFilePath, JSON.stringify(cacheData)); + + // Serve the response + res.writeHead(proxyRes.statusCode, proxyRes.headers); + res.end(responseData); + }); + }).on('error', (err) => { + res.writeHead(500, { 'Content-Type': 'text/plain' }); + res.end('Error fetching the resource'); + }); +}; + +// Create an HTTP server +const server = http.createServer(handleRequest); + +server.listen(PORT, () => { + console.log(`Proxy server running at http://localhost:${PORT}`); +});