/opt/canhelp/apps/web/src
NameSizeModeActions
app/-0755rm
components/-0755rm
context/-0755rm
hooks/-0755rm
lib/-0755rm
types/-0755rm
middleware.ts20730644editdlrm
Edit: /opt/canhelp/apps/web/src/middleware.ts (2073B)
import { NextRequest, NextResponse } from 'next/server' // Module-level cache for maintenance check — Edge runtime doesn't support Next.js data cache let maintenanceCached: boolean | null = null let maintenanceCacheExpiry = 0 export async function middleware(request: NextRequest) { const { pathname } = request.nextUrl // Pass pathname to layouts via request header const requestHeaders = new Headers(request.headers) requestHeaders.set('x-pathname', pathname) // Skip admin, login/auth, maintenance page itself, API, static assets, and SEO files if ( pathname.startsWith('/admin') || pathname.startsWith('/login') || pathname.startsWith('/register') || pathname.startsWith('/auth') || pathname.startsWith('/maintenance') || pathname.startsWith('/api') || pathname.startsWith('/_next') || pathname.startsWith('/fonts') || pathname === '/sitemap.xml' || pathname === '/robots.txt' || pathname.match(/\.(ico|png|jpg|jpeg|svg|webp|css|js|xml|txt)$/) ) { return NextResponse.next({ request: { headers: requestHeaders } }) } try { const now = Date.now() let isMaintenance: boolean if (now < maintenanceCacheExpiry && maintenanceCached !== null) { isMaintenance = maintenanceCached } else { const apiBase = process.env.INTERNAL_API_URL || 'http://localhost:4000' const res = await fetch(`${apiBase}/api/admin/seo-public`) if (res.ok) { const settings: Record = await res.json() isMaintenance = settings['seo.maintenanceMode'] === 'true' maintenanceCached = isMaintenance maintenanceCacheExpiry = now + 30_000 } else { isMaintenance = false } } if (isMaintenance) { return NextResponse.redirect(new URL('/maintenance', request.url)) } } catch { // If API is unreachable, allow access — don't block the site } return NextResponse.next({ request: { headers: requestHeaders } }) } export const config = { matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'], }