ai generated solutions to our ai generated problems
This commit is contained in:
@@ -89,7 +89,9 @@ the upstream response, rate limits callers, and caches successful GET responses.
|
||||
Public TSS reads are also written to a bounded JSON snapshot cache and served at
|
||||
both their `/api/tss/*` route and matching `/data/*` path. Fresh snapshots return
|
||||
without touching the backend; stale snapshots are served immediately while the
|
||||
server refreshes them in the background. All responses
|
||||
server refreshes them in the background. The frontend uses `/api/tss/*` by
|
||||
default so it can hit this server-side cache directly; set `VITE_STATIC_DATA=true`
|
||||
only if you explicitly want the client to try `/data/*` first. All responses
|
||||
ship `X-Content-Type-Options`, `X-Frame-Options: DENY`, `Referrer-Policy`,
|
||||
`Permissions-Policy`, `Cross-Origin-Opener-Policy`, `Cross-Origin-Resource-Policy`,
|
||||
HSTS (over HTTPS), and HTML responses include a Content Security Policy that
|
||||
@@ -116,6 +118,7 @@ PUBLIC_DATA_CACHE_DIR=~/tsswebstorage/public-data
|
||||
PUBLIC_DATA_CACHE_FRESH_MS=300000
|
||||
PUBLIC_DATA_CACHE_STALE_MS=86400000
|
||||
PUBLIC_DATA_PREWARM_INTERVAL_MS=300000
|
||||
VITE_STATIC_DATA=false
|
||||
API_RATE_LIMIT_WINDOW_MS=60000
|
||||
API_RATE_LIMIT_MAX=120
|
||||
```
|
||||
|
||||
@@ -61,3 +61,4 @@ DISCORD_INCLUDE_PATCH=true
|
||||
# TURNSTILE_SECRET_KEY is the server-only secret used to call the Siteverify endpoint.
|
||||
VITE_TURNSTILE_SITE_KEY=
|
||||
TURNSTILE_SECRET_KEY=
|
||||
VITE_STATIC_DATA=false
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
# Static Public Data
|
||||
|
||||
The frontend tries these JSON snapshots before falling back to the live API:
|
||||
The frontend can try these JSON snapshots before falling back to the live API
|
||||
when `VITE_STATIC_DATA=true`. By default, the app requests `/api/tss/*` directly
|
||||
and lets the web server answer from the same public data cache.
|
||||
|
||||
- `/data/leaderboard-teams.json`
|
||||
- `/data/leaderboard-players.json`
|
||||
|
||||
@@ -51,7 +51,7 @@ const siteVersion = '1.0.1'
|
||||
|
||||
const turnstileSiteKey = import.meta.env.VITE_TURNSTILE_SITE_KEY || ''
|
||||
const staticDataBase = (import.meta.env.VITE_STATIC_DATA_BASE || '/data').replace(/\/+$/, '')
|
||||
const staticDataEnabled = String(import.meta.env.VITE_STATIC_DATA || 'true').toLowerCase() !== 'false'
|
||||
const staticDataEnabled = String(import.meta.env.VITE_STATIC_DATA || 'false').toLowerCase() === 'true'
|
||||
const missingStaticDataPaths = new Set()
|
||||
|
||||
const defaultAnalyticsPreferences = {
|
||||
|
||||
+7
-2
@@ -54,6 +54,8 @@ const PUBLIC_DATA_CACHE_DIR = path.resolve(
|
||||
const PUBLIC_DATA_CACHE_FRESH_MS = Number(process.env.PUBLIC_DATA_CACHE_FRESH_MS || 5 * 60 * 1000)
|
||||
const PUBLIC_DATA_CACHE_STALE_MS = Number(process.env.PUBLIC_DATA_CACHE_STALE_MS || 24 * 60 * 60 * 1000)
|
||||
const PUBLIC_DATA_PREWARM_INTERVAL_MS = Number(process.env.PUBLIC_DATA_PREWARM_INTERVAL_MS || PUBLIC_DATA_CACHE_FRESH_MS)
|
||||
const PUBLIC_DATA_CACHE_MAX_AGE_SECONDS = Math.max(0, Math.floor(PUBLIC_DATA_CACHE_FRESH_MS / 1000))
|
||||
const PUBLIC_DATA_STALE_REVALIDATE_SECONDS = Math.max(0, Math.floor(PUBLIC_DATA_CACHE_STALE_MS / 1000))
|
||||
const API_RATE_LIMIT_WINDOW_MS = Number(process.env.API_RATE_LIMIT_WINDOW_MS || 60000)
|
||||
const API_RATE_LIMIT_MAX = Number(process.env.API_RATE_LIMIT_MAX || 120)
|
||||
const TURNSTILE_SECRET_KEY = process.env.TURNSTILE_SECRET_KEY || ''
|
||||
@@ -293,7 +295,7 @@ function sendPublicDataFile(req, res, filePath, status = 200, extraHeaders = {})
|
||||
|
||||
send(res, status, data, {
|
||||
'content-type': 'application/json; charset=utf-8',
|
||||
'cache-control': 'public, max-age=30, stale-while-revalidate=300',
|
||||
'cache-control': `public, max-age=${PUBLIC_DATA_CACHE_MAX_AGE_SECONDS}, stale-while-revalidate=${PUBLIC_DATA_STALE_REVALIDATE_SECONDS}`,
|
||||
...extraHeaders,
|
||||
})
|
||||
})
|
||||
@@ -1948,8 +1950,11 @@ function proxyRequest(req, res) {
|
||||
const headers = {
|
||||
...proxyRes.headers,
|
||||
...securityHeaders(req),
|
||||
'cache-control': publicDataFile ? 'public, max-age=30, stale-while-revalidate=300' : 'private, max-age=15',
|
||||
'cache-control': publicDataFile
|
||||
? `public, max-age=${PUBLIC_DATA_CACHE_MAX_AGE_SECONDS}, stale-while-revalidate=${PUBLIC_DATA_STALE_REVALIDATE_SECONDS}`
|
||||
: 'private, max-age=15',
|
||||
}
|
||||
if (publicDataFile) headers['x-tssbot-cache'] = 'public-data-miss'
|
||||
|
||||
delete headers['access-control-allow-origin']
|
||||
delete headers['access-control-allow-credentials']
|
||||
|
||||
Reference in New Issue
Block a user