From 627a1a0d9e835f0dc00633270a1d2efcdf1dd76f Mon Sep 17 00:00:00 2001 From: Dorian Date: Mon, 9 Mar 2026 00:24:48 +0000 Subject: [PATCH] perf: CDN-ready caching headers and compression Co-Authored-By: Claude Opus 4.6 --- server/src/app.ts | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/server/src/app.ts b/server/src/app.ts index 4716a66..1424e0a 100644 --- a/server/src/app.ts +++ b/server/src/app.ts @@ -52,6 +52,28 @@ app.use('/api/*', bodyLimit({ maxSize: 256 * 1024 })) // Rate limit all POST endpoints (60/min per IP) app.use('/api/*', rateLimit(60_000, 60)) +// API cache headers +app.use('/api/*', async (c, next) => { + await next() + // Default: no-store for dynamic data + if (!c.res.headers.has('Cache-Control')) { + c.header('Cache-Control', 'no-store') + } +}) +// Leaderboard and public stats can be cached briefly +app.use('/api/bots/leaderboard', async (c, next) => { + await next() + c.header('Cache-Control', 'public, max-age=60') +}) +app.use('/api/stats/public', async (c, next) => { + await next() + c.header('Cache-Control', 'public, max-age=300') +}) +app.use('/api/docs/*', async (c, next) => { + await next() + if (c.req.method === 'GET') c.header('Cache-Control', 'public, max-age=3600') +}) + app.get('/api/health', (c) => c.json({ status: 'ok', name: 'botfights' })) app.route('/api/auth', authRouter)