Created
January 30, 2025 18:55
-
-
Save AdventureBear/87ebc3ffbd64d04a877d49043866fb30 to your computer and use it in GitHub Desktop.
middleware
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { NextRequest, NextResponse } from 'next/server' | |
import { stateNames } from '@/app/lib/utils' | |
import cities from '@/data/cities' | |
import { slugify } from '@/app/lib/utils' | |
import { NextURL } from 'next/dist/server/web/next-url'; | |
export async function middleware(req: NextRequest) { | |
const url = new NextURL(req.url) | |
const pathname = url.pathname | |
console.log('Middleware processing:', pathname) | |
// Ensure that the redirects don't affect the general /cities, /courses, or /states routes | |
if (pathname === '/cities' || pathname === '/courses' || pathname === '/states' || pathname === '/sitemap.xml' || pathname === '/api/sitemap.xml') { | |
return NextResponse.next(); // Allow the default page behavior (e.g., listing all cities, states, or courses) | |
} | |
// Skip if not a state-related path | |
if (!pathname.startsWith('/states/')) { | |
return NextResponse.next() | |
} | |
// Split pathname into segments | |
const segments = pathname.split('/').filter(Boolean) | |
// Get the state segment (should be first segment after /states/) | |
const stateSlug = segments[1] | |
const citySlug = segments[2]; | |
const courseSlug = segments[3]; | |
if (!stateSlug) { | |
return NextResponse.next() | |
} | |
// Check if it's a valid state - check both full name and code | |
const stateCode = Object.entries(stateNames).find(([code, name]) => | |
slugify(name) === stateSlug.toLowerCase() || code === stateSlug.toUpperCase() | |
)?.[0] | |
console.log('State slug:', stateSlug) | |
console.log('State code found:', stateCode) | |
console.log('State name:', stateCode ? stateNames[stateCode] : 'not found') | |
// Redirect if state isn't properly slugified OR if any segment contains URL-encoded characters | |
if (stateCode && ( | |
stateSlug !== slugify(stateNames[stateCode]) || | |
segments.some(segment => segment.includes('%')) | |
)) { | |
const newSegments = segments.map((segment, index) => { | |
if (index === 1) { | |
// State segment | |
return slugify(stateNames[stateCode]) | |
} else if (index === 2) { | |
// City segment | |
return slugify(decodeURIComponent(segment)) | |
} else if (index === 3) { | |
// Course segment | |
return slugify(decodeURIComponent(segment)) | |
} | |
return segment | |
}) | |
const newPathname = '/' + newSegments.join('/') | |
console.log('Redirecting to:', newPathname) | |
return NextResponse.redirect(new URL(newPathname, req.url)) | |
} | |
// If there's a city segment, validate it | |
// const citySlug = segments[2] | |
if (citySlug && stateCode) { | |
const decodedCitySlug = decodeURIComponent(citySlug) | |
const isValidCity = cities.some((city: string) => { | |
const [cityName, stateName] = city.split(', ') | |
return slugify(cityName) === slugify(decodedCitySlug) && | |
stateCode ? slugify(stateName) === slugify(stateNames[stateCode]) : false | |
}) | |
console.log(`Checking city: ${decodedCitySlug} for state: ${stateCode ? stateNames[stateCode] : 'unknown'}`) | |
console.log("Is Valid City: ", isValidCity) | |
// Check city is not in the database but a course is present, search for the course | |
if (!isValidCity && courseSlug) { | |
return NextResponse.next(); // Allow request if the course exists | |
} | |
if (!isValidCity) { | |
return NextResponse.redirect(new URL(`/states/${stateSlug}`, req.url)) | |
} | |
} | |
console.log("URL is valid: ", req.url) | |
return NextResponse.next() | |
} | |
// Make sure middleware matches all relevant paths | |
// export const config = { | |
// matcher: ['/states/:path*'] | |
// } | |
export const config = { | |
matcher: [ | |
// Only match state/city/course patterns | |
'/states/:state/:city/:course*', | |
// Match state/city patterns | |
'/states/:state/:city', | |
// Match direct state patterns | |
'/states/:state' | |
] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment