feat(web): serve vehicle icons statically + deploy symlink + dev guard for logs/lang

This commit is contained in:
FURRO404
2026-06-18 00:38:00 -07:00
parent 49e75cc8f0
commit 177ddd408d
3 changed files with 63 additions and 0 deletions
+33
View File
@@ -56,6 +56,10 @@ const TURNSTILE_VERIFY_TIMEOUT_MS = Number(process.env.TURNSTILE_VERIFY_TIMEOUT_
const TURNSTILE_MAX_TOKEN_LENGTH = 2048
const TURNSTILE_TOKEN_MAX_AGE_MS = 5 * 60 * 1000
const DIST_DIR = path.join(__dirname, 'dist')
const VEHICLE_ICONS_DIR = path.resolve(
__dirname,
process.env.VEHICLE_ICONS_DIR || path.join('dist', 'vehicle-icons'),
)
const MAX_TEAM_NAME_LENGTH = 80
const MAX_CACHE_ENTRIES = 200
const MAX_RATE_LIMIT_KEYS = 1000
@@ -2027,6 +2031,30 @@ function serveStatic(req, res) {
})
}
function serveVehicleIcon(req, res) {
let requestPath = '/'
try {
requestPath = decodeURIComponent(new URL(req.url, `http://localhost:${PORT}`).pathname)
} catch {
return send(res, 400, 'Bad request', { 'content-type': 'text/plain; charset=utf-8' })
}
const name = requestPath.slice('/vehicle-icons/'.length)
const filePath = path.resolve(VEHICLE_ICONS_DIR, `./${name}`)
const relative = path.relative(VEHICLE_ICONS_DIR, filePath)
if (relative.startsWith('..') || path.isAbsolute(relative) || path.extname(filePath) !== '.png') {
return send(res, 403, 'Forbidden', { 'content-type': 'text/plain; charset=utf-8' })
}
fs.readFile(filePath, (error, data) => {
if (error) {
return send(res, 404, 'Not found', { 'content-type': 'text/plain; charset=utf-8' })
}
send(res, 200, data, {
'content-type': 'image/png',
'cache-control': 'public, max-age=604800',
})
})
}
const server = http.createServer((req, res) => {
if (req.method === 'GET' && req.url === '/robots.txt') {
sendRobotsTxt(req, res)
@@ -2152,6 +2180,11 @@ const server = http.createServer((req, res) => {
return
}
if (req.method === 'GET' && req.url.startsWith('/vehicle-icons/')) {
serveVehicleIcon(req, res)
return
}
if (req.url.startsWith('/api/')) {
proxyRequest(req, res)
return