import { NextResponse } from "next/server"; import type { NextRequest } from "next/server"; import { CYBERLUX_ENTRY_COOKIE, parseCyberluxEntry, type CyberluxEntry, } from "@/lib/cyberluxEntry"; import { DEDICATED_ROOT } from "@/lib/onionRoutes.generated"; import { isOnionCrossNavPath } from "@/lib/cyberluxCrossNav"; /** Set by nginx per Tor vhost: `proxy_set_header X-Cyberlux-Node ;` */ function entryFromRequest(request: NextRequest): CyberluxEntry { return parseCyberluxEntry(request.headers.get("x-cyberlux-node")); } function isCrossNavPath(pathname: string): boolean { return isOnionCrossNavPath(pathname); } function withEntryCookie(res: NextResponse, request: NextRequest): NextResponse { const entry = entryFromRequest(request); res.cookies.set(CYBERLUX_ENTRY_COOKIE, entry, { path: "/", sameSite: "lax", maxAge: 60 * 60 * 24 * 400, httpOnly: false, }); return res; } function handleDedicatedRoot( request: NextRequest, pathname: string, root: string, ): NextResponse { if (isCrossNavPath(pathname)) { return withEntryCookie(NextResponse.next(), request); } const suffix = pathname === "/" ? "" : pathname; return withEntryCookie( NextResponse.rewrite(new URL(`${root}${suffix}`, request.url)), request, ); } /** * Next.js 16+ proxy (replaces `middleware.ts`). Runs on Node; no `export const config` here. */ export function proxy(request: NextRequest) { const { pathname } = request.nextUrl; const entry = entryFromRequest(request); if (pathname.startsWith("/_next") || pathname.startsWith("/favicon")) { return withEntryCookie(NextResponse.next(), request); } // Same idea as legacy middleware `matcher`: skip typical static files if (/\.[a-zA-Z0-9]{2,5}$/.test(pathname)) { return withEntryCookie(NextResponse.next(), request); } if (entry === "wiki") { if (isCrossNavPath(pathname)) { return withEntryCookie(NextResponse.next(), request); } return withEntryCookie( NextResponse.rewrite(new URL("/hidden-wiki", request.url)), request, ); } if (entry === "w") { if (isCrossNavPath(pathname)) { return withEntryCookie(NextResponse.next(), request); } if (pathname === "/") { return withEntryCookie( NextResponse.rewrite(new URL("/syndicate", request.url)), request, ); } const rest = pathname.startsWith("/") ? pathname.slice(1) : pathname; return withEntryCookie( NextResponse.rewrite(new URL(`/w/${rest}`, request.url)), request, ); } if (entry !== "hub" && entry in DEDICATED_ROOT) { const root = DEDICATED_ROOT[entry as keyof typeof DEDICATED_ROOT]; return handleDedicatedRoot(request, pathname, root); } return withEntryCookie(NextResponse.next(), request); }