Files

68 lines
2.3 KiB
TypeScript

import { NextRequest } from "next/server";
// Server-side URL of the K-TV backend (never exposed to the browser).
// Falls back to the public URL if the internal one isn't set.
const API_URL =
process.env.API_URL ??
process.env.NEXT_PUBLIC_API_URL ??
"http://localhost:4000/api/v1";
/**
* GET /api/stream/[channelId]?token=<bearer>
*
* Resolves the backend's 307 stream redirect and returns the final
* Jellyfin URL as JSON. Browsers can't read the Location header from a
* redirected fetch, so this server-side route does it for them.
*
* Returns:
* 200 { url: string } — stream URL ready to use as <video src>
* 204 — channel is in a gap (no-signal)
* 401 — missing token
* 502 — backend error
*/
export async function GET(
request: NextRequest,
{ params }: { params: Promise<{ channelId: string }> },
) {
const { channelId } = await params;
const token = request.nextUrl.searchParams.get("token");
const channelPassword = request.nextUrl.searchParams.get("channel_password");
const blockPassword = request.nextUrl.searchParams.get("block_password");
const quality = request.nextUrl.searchParams.get("quality");
let res: Response;
try {
const headers: Record<string, string> = {};
if (token) headers["Authorization"] = `Bearer ${token}`;
if (channelPassword) headers["X-Channel-Password"] = channelPassword;
if (blockPassword) headers["X-Block-Password"] = blockPassword;
const backendParams = new URLSearchParams();
if (quality) backendParams.set("quality", quality);
const backendQuery = backendParams.toString() ? `?${backendParams}` : "";
res = await fetch(`${API_URL}/channels/${channelId}/stream${backendQuery}`, {
headers,
redirect: "manual",
});
} catch {
return new Response(null, { status: 502 });
}
if (res.status === 204) {
return new Response(null, { status: 204 });
}
if (res.status === 401 || res.status === 403) {
const body = await res.json().catch(() => ({}));
return Response.json(body, { status: res.status });
}
if (res.status === 307 || res.status === 302 || res.status === 301) {
const location = res.headers.get("Location");
if (location) {
return Response.json({ url: location });
}
}
return new Response(null, { status: 502 });
}