35 lines
1.5 KiB
TypeScript
35 lines
1.5 KiB
TypeScript
import { NextResponse, type NextRequest } from "next/server";
|
|
import { ProviderError } from "./http";
|
|
|
|
/** Turns any thrown error into a JSON `{ error }` response with a sensible status. */
|
|
export function errorResponse(error: unknown): NextResponse {
|
|
if (error instanceof ProviderError) {
|
|
return NextResponse.json({ error: error.message }, { status: error.status });
|
|
}
|
|
console.error(error);
|
|
return NextResponse.json({ error: "Something went wrong reaching the weather service" }, { status: 500 });
|
|
}
|
|
|
|
export function badRequest(message: string): NextResponse {
|
|
return NextResponse.json({ error: message }, { status: 400 });
|
|
}
|
|
|
|
/** Rejects cross-site browser requests so external pages can't hotlink your API/tile quotas. */
|
|
export function forbidCrossSite(request: NextRequest): NextResponse | null {
|
|
if (request.headers.get("sec-fetch-site") === "cross-site") {
|
|
return NextResponse.json({ error: "Cross-site requests are not permitted" }, { status: 403 });
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/** Parses a lat/lon pair from query params, or returns null if either is missing or invalid. */
|
|
export function parseCoords(params: URLSearchParams): { lat: number; lon: number } | null {
|
|
const rawLat = params.get("lat")?.trim() ?? "";
|
|
const rawLon = params.get("lon")?.trim() ?? "";
|
|
if (!rawLat || !rawLon) return null;
|
|
|
|
const lat = Number(rawLat);
|
|
const lon = Number(rawLon);
|
|
const valid = Number.isFinite(lat) && Number.isFinite(lon) && Math.abs(lat) <= 90 && Math.abs(lon) <= 180;
|
|
return valid ? { lat, lon } : null;
|
|
}
|