the best ios gas tracking app
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}