feat: build production-ready wtr weather PWA
This commit is contained in:
39
app/api/imgw/[...path]/route.ts
Normal file
39
app/api/imgw/[...path]/route.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
const ALLOWED_PATHS = new Set([
|
||||
"synop",
|
||||
"hydro",
|
||||
"meteo",
|
||||
"warningsmeteo",
|
||||
"warningshydro",
|
||||
"product",
|
||||
]);
|
||||
const IMGW_BASE_URL = "https://danepubliczne.imgw.pl/api/data";
|
||||
|
||||
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" },
|
||||
});
|
||||
if (!response.ok) {
|
||||
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 });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user