gate: no-store on all responses (prevent CDN cache bypass)

This commit is contained in:
mosaic 2026-09-09 16:47:33 +00:00
parent 6c85055e79
commit d14323b664
1 changed files with 6 additions and 2 deletions

View File

@ -59,8 +59,12 @@ button:hover{background:#3a80c6}.err{color:#f0857d;font-size:12px;margin-top:12p
<div class="err">${err ? 'Incorrect passphrase.' : ''}</div></div></body></html>`;
}
// Every response must be uncacheable — otherwise the CDN could cache a gated file
// under its URL and serve it to unauthenticated visitors (bypassing the gate), or
// cache a lock page and show it to authenticated ones.
const NOCACHE = { 'Cache-Control': 'no-store, no-cache, must-revalidate, private', 'Pragma': 'no-cache', 'Vary': 'Cookie' };
function send(res, code, type, body, extra) {
const h = { 'Content-Type': type, 'X-Robots-Tag': 'noindex, nofollow', ...(extra || {}) };
const h = { 'Content-Type': type, 'X-Robots-Tag': 'noindex, nofollow', ...NOCACHE, ...(extra || {}) };
res.writeHead(code, h); res.end(body);
}
@ -100,7 +104,7 @@ http.createServer((req, res) => {
const base = path.basename(abs);
if (BLOCK.has(base) || abs.includes('/node_modules/') || abs.includes('/.git/')) { send(res, 404, 'text/plain', 'not found'); return; }
const type = MIME[path.extname(abs).toLowerCase()] || 'application/octet-stream';
res.writeHead(200, { 'Content-Type': type, 'X-Robots-Tag': 'noindex, nofollow' });
res.writeHead(200, { 'Content-Type': type, 'X-Robots-Tag': 'noindex, nofollow', ...NOCACHE });
fs.createReadStream(abs).pipe(res);
} catch (_) { send(res, 404, 'text/html; charset=utf-8', '<h1>404</h1>'); }
}).listen(PORT, () => console.log('gate proxy on ' + PORT));