import { NextRequest, NextResponse } from "next/server" import { pingServer, verifyToken } from "@shared/api/server" import { ENTRY_PATHS_REGEXP, EXCLUDE_PATHS_REGEXP } from "@shared/lib/constants" const redirector = async ({ pathname, queryString, headers, initialPath, endPath, origin, }: { initialPath: string endPath: string pathname: string queryString: string origin: string headers: Headers }) => { if (pathname.includes(initialPath)) { const sp = queryString.length ? `?${queryString}` : "" const finalURL = `${origin}${pathname.replace(initialPath, endPath)}${sp}` return NextResponse.redirect(finalURL, { headers }) } } const redirections: { from: string; to: string }[] = [] export async function proxy(req: NextRequest) { // Base URL data from nextjs const { origin, pathname, searchParams } = req.nextUrl // Headers data from nextjs const headers = new Headers(req.headers) // Token data from cookies const token = req.cookies.get("access_token")?.value // Server status check const isServerAlive = (await pingServer()) !== false // Entry paths checkers const isEntryPath = ENTRY_PATHS_REGEXP.test(pathname) const isExcludedPath = EXCLUDE_PATHS_REGEXP.test(pathname) // Stringified qs const queryParams = searchParams.toString() // Set current path header for analytics purposes headers.set("x-current-path", req.nextUrl.pathname) // Redirect to under_maintenance if server is down if (!isServerAlive && pathname !== "/under_maintenance") { return NextResponse.redirect( `${origin}/under_maintenance?path=${pathname}${queryParams}`, { headers }, ) } // Verify user if page is not public if (!isExcludedPath && isServerAlive) { const isVerified = token && (await verifyToken(token).catch((e) => { console.error( "Middleware verification error\n", String(e).toLowerCase(), ) return null })) if (isVerified && isEntryPath) { return NextResponse.redirect(`${origin}/`, { headers }) } if (!isVerified && !isEntryPath) { const returnParam = pathname === "/" ? "" : `?from=${pathname}` return NextResponse.redirect(`${origin}/login${returnParam}`, { headers }) } } for (const redirection of redirections) { const redirect = await redirector({ pathname, headers, origin, initialPath: redirection.from, endPath: redirection.to, queryString: searchParams.toString(), }) if (redirect) { return redirect } } return NextResponse.next({ headers, request: { headers } }) } export const config = { matcher: [ { source: "/((?!api|_next/static|_next/image|favicon.ico).*)", missing: [ { type: "header", key: "next-router-prefetch" }, { type: "header", key: "next-action" }, { type: "header", key: "purpose", value: "prefetch" }, ], }, ], }