105 lines
2.7 KiB
TypeScript
105 lines
2.7 KiB
TypeScript
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" },
|
|
],
|
|
},
|
|
],
|
|
}
|