Files
dark-lord/proxy.ts
drjones 04d64fb993 Update market, account, and onion operations
Capture the current CyberLux UI, commerce, messaging, and Tor ops updates so local main can be pushed to the remote.

Made-with: Cursor
2026-04-24 23:23:48 -07:00

95 lines
2.7 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";
import { isOnionCrossNavPath } from "@/lib/cyberluxCrossNav";
/** 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"));
}
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);
}