Files
wtr/app/api/imgw/[...path]/route.ts
zv ee55521803
All checks were successful
CI / Lint, typecheck and build (push) Successful in 9m56s
chore: add prettier formatting
2026-06-14 20:26:56 +02:00

45 lines
1.9 KiB
TypeScript

import { NextResponse } from "next/server";
import { isImgwNoProductsResponse, readImgwResponseBody } from "@/lib/imgw-empty-response";
const ALLOWED_PATHS = new Set(["synop", "hydro", "meteo", "warningsmeteo", "warningshydro", "product"]);
const IMGW_BASE_URL = "https://danepubliczne.imgw.pl/api/data";
const USER_AGENT = "wtr./1.0 (weather data proxy)";
export async function GET(_: Request, context: { params: Promise<{ path: string[] }> }) {
const { path } = await context.params;
const [resource, variant, value] = path;
const isAllowedSynopDetail = resource === "synop" && variant === "id" && Boolean(value) && path.length === 3;
const isAllowedCollection = ALLOWED_PATHS.has(resource) && path.length === 1;
if (!isAllowedSynopDetail && !isAllowedCollection) {
return NextResponse.json({ error: "Nieobsługiwana ścieżka IMGW." }, { status: 404 });
}
const upstreamPath = path.map(encodeURIComponent).join("/");
try {
const response = await fetch(`${IMGW_BASE_URL}/${upstreamPath}`, {
next: { revalidate: 300 },
headers: { Accept: "application/json", "User-Agent": USER_AGENT },
});
if (!response.ok) {
const body = await readImgwResponseBody(response);
if (
(resource === "warningsmeteo" || resource === "warningshydro") &&
response.status === 404 &&
isImgwNoProductsResponse(body.json)
) {
return NextResponse.json([], {
headers: { "Cache-Control": "public, s-maxage=300, stale-while-revalidate=600" },
});
}
return NextResponse.json({ error: "IMGW API jest chwilowo niedostępne." }, { status: response.status });
}
const data: unknown = await response.json();
return NextResponse.json(data, {
headers: { "Cache-Control": "public, s-maxage=300, stale-while-revalidate=600" },
});
} catch {
return NextResponse.json({ error: "Nie udało się połączyć z IMGW API." }, { status: 502 });
}
}