Shumiland/src/middleware.ts
Vadym Samoilenko bf084e37c9 feat(cms): add redirects plugin + middleware for 301/302 handling
Install @payloadcms/plugin-redirects, configure for 'pages' collection
with 301/302 types. Create src/middleware.ts that reads the redirects
collection via REST API (cached 5 min) and applies them before Next.js
renders — editors can manage redirects from the CMS admin.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 16:56:30 +01:00

47 lines
1.4 KiB
TypeScript

import type { NextRequest } from 'next/server'
import { NextResponse } from 'next/server'
let redirectsCache: { from: string; to: string; type: string }[] | null = null
let cacheExpiry = 0
async function getRedirects(siteURL: string) {
if (redirectsCache && Date.now() < cacheExpiry) return redirectsCache
try {
const res = await fetch(`${siteURL}/api/redirects?limit=100&depth=1`, {
next: { revalidate: 300 },
})
if (!res.ok) return []
const data = (await res.json()) as {
docs: { from: string; to: { url?: string }; redirectType: string }[]
}
redirectsCache = data.docs.map((r) => ({
from: r.from,
to: r.to?.url ?? '/',
type: r.redirectType,
}))
cacheExpiry = Date.now() + 5 * 60 * 1000
return redirectsCache
} catch {
return []
}
}
export async function middleware(request: NextRequest) {
const siteURL = process.env['NEXT_PUBLIC_SITE_URL'] ?? 'http://localhost:3000'
const pathname = request.nextUrl.pathname
const redirects = await getRedirects(siteURL)
const match = redirects.find((r) => r.from === pathname)
if (match) {
const status = match.type === '302' ? 302 : 301
return NextResponse.redirect(new URL(match.to, request.url), status)
}
return NextResponse.next()
}
export const config = {
matcher: ['/((?!_next/static|_next/image|favicon.ico|api/|admin/).*)'],
}