Add persistent onion key backup and restore, improve startup resilience, and flesh out the major site verticals with richer navigation, search coverage, and operator documentation. Made-with: Cursor
145 lines
3.5 KiB
TypeScript
145 lines
3.5 KiB
TypeScript
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";
|
|
|
|
/** Set by nginx per Tor vhost: `proxy_set_header X-Cyberlux-Node <node>;` */
|
|
function entryFromRequest(request: NextRequest): CyberluxEntry {
|
|
return parseCyberluxEntry(request.headers.get("x-cyberlux-node"));
|
|
}
|
|
|
|
/**
|
|
* Paths that must not be prefixed when using a dedicated entry onion.
|
|
* Keep in sync with top-level `app/<segment>/` routes.
|
|
*/
|
|
const CROSS_NAV_PREFIXES = [
|
|
"/account",
|
|
"/api",
|
|
"/arb-academy",
|
|
"/awards",
|
|
"/barter",
|
|
"/chatter",
|
|
"/checkout",
|
|
"/comparison",
|
|
"/conspiracies",
|
|
"/darknet-atlas",
|
|
"/dashboard",
|
|
"/drop-box",
|
|
"/drops",
|
|
"/easter-eggs",
|
|
"/exchange",
|
|
"/forum",
|
|
"/game",
|
|
"/hidden-wiki",
|
|
"/inner-circle",
|
|
"/links",
|
|
"/market",
|
|
"/messages",
|
|
"/mixer",
|
|
"/presswire",
|
|
"/raffle",
|
|
"/red-room",
|
|
"/reviews",
|
|
"/sanctuary",
|
|
"/search",
|
|
"/secret-layer",
|
|
"/security-analysis",
|
|
"/sign-in",
|
|
"/sign-up",
|
|
"/support",
|
|
"/syndicate",
|
|
"/testimonials",
|
|
"/trees",
|
|
"/trust",
|
|
"/vault",
|
|
"/vendor",
|
|
"/vendors",
|
|
"/wallets",
|
|
"/webring",
|
|
"/w/",
|
|
] as const;
|
|
|
|
function isCrossNavPath(pathname: string): boolean {
|
|
return CROSS_NAV_PREFIXES.some((p) => pathname.startsWith(p));
|
|
}
|
|
|
|
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);
|
|
}
|