the best ios gas tracking app
at main 47 lines 1.6 kB view raw
1import { checkRateLimit, lookupApiKey } from "./db.ts"; 2 3export function json(data: unknown, status = 200): Response { 4 return Response.json(data, { status }); 5} 6 7export function err(message: string, status: number): Response { 8 return json({ error: message }, status); 9} 10 11export function bearerToken(request: Request): string | null { 12 const header = request.headers.get("Authorization"); 13 if (!header?.startsWith("Bearer ")) return null; 14 return header.slice(7).trim(); 15} 16 17export function requireDeviceSecret(request: Request): Response | null { 18 const token = bearerToken(request); 19 const secret = process.env.GASTRACK_DEVICE_SECRET; 20 if (!secret) { 21 console.error("GASTRACK_DEVICE_SECRET not set"); 22 return err("Server misconfigured", 500); 23 } 24 if (token !== secret) { 25 console.error( 26 `Auth mismatch — got: "${token?.slice(0, 6)}…" expected: "${secret.slice(0, 6)}…"`, 27 ); 28 return err("Unauthorized", 401); 29 } 30 return null; 31} 32 33export function requireApiKey(request: Request): Response | null { 34 const token = bearerToken(request); 35 if (!token) return err("Missing Authorization header", 401); 36 if (!lookupApiKey(token)) return err("Invalid API key", 401); 37 if (!checkRateLimit(token)) return err("Rate limit exceeded", 429); 38 return null; 39} 40 41// Auth-only, no rate limit. Use for cache-only endpoints that never call upstream APIs. 42export function requireApiKeyNoRateLimit(request: Request): Response | null { 43 const token = bearerToken(request); 44 if (!token) return err("Missing Authorization header", 401); 45 if (!lookupApiKey(token)) return err("Invalid API key", 401); 46 return null; 47}