From bba81e725ffda78ba05ea7383463e8df0eab64f4 Mon Sep 17 00:00:00 2001 From: Maedah Batool Date: Sat, 25 Jan 2025 22:20:32 +0500 Subject: [PATCH] Fix redirects issue --- src/middleware.ts | 219 ++++++++++++++++++++++++++++------------------ 1 file changed, 136 insertions(+), 83 deletions(-) diff --git a/src/middleware.ts b/src/middleware.ts index ea508acda..9c237a9e8 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -1,88 +1,141 @@ -import { NextResponse } from 'next/server' -import type { NextRequest } from 'next/server' -import docsConfig from '../docs.config.js' - -const { updatedRedirectsData } = require('./data/redirects.ts'); - -function createRedirectUrl(request: NextRequest, destination: string, path: string): string { - // Handle absolute URLs - if (destination.startsWith('http')) { - // Handle dynamic slug replacements - if (destination.includes(':slug')) { - const slugMatch = path.match(/[^/]+$/) - const slug = slugMatch ? slugMatch[0] : '' - destination = destination.replace(':slug*', slug) - } - // Handle version replacements - if (destination.includes(':version')) { - const versionMatch = path.match(/\d+\.\d+/) - const version = versionMatch ? versionMatch[0] : '' - destination = destination.replace(':version', version) - } - - return destination - } - - // Handle relative paths - const basePath = '/docs' - return destination.startsWith('/') ? - `${request.nextUrl.origin}${basePath}${destination}` : - `${request.nextUrl.origin}${basePath}/${destination}` -} +import type { NextRequest } from 'next/server'; +import { NextResponse } from 'next/server'; +import docsConfig from '../docs.config.js'; + +const {updatedRedirectsData} = require('./data/redirects.ts'); + +function createRedirectUrl( + request: NextRequest, + destination: string, + path: string +): string { + // Handle absolute URLs + if (destination.startsWith('http')) { + // Extract version and full path after version + const versionMatch = path.match(/(?:\/v\/|@)(\d+\.\d+)\/(.*)/); + + if (versionMatch) { + const version = versionMatch[1]; + const remainingPath = versionMatch[2]; + + // Find matching redirect for the remaining path + const redirect = updatedRedirectsData.find( + (r: any) => + r.source === `/${remainingPath}` || + r.source === remainingPath + ); + + // If redirect exists, use its destination, otherwise use the remaining path + const finalPath = redirect + ? redirect.destination.replace(/^\//, '') + : remainingPath; + + // Replace placeholders and construct final URL + return destination + .replace(':version', version) + .replace(':slug*', finalPath); + } + + // Handle other cases as before + if (destination.includes(':slug')) { + const slugMatch = path.match(/[^/]+$/); + const slug = slugMatch ? slugMatch[0] : ''; + destination = destination.replace(':slug*', slug); + } + + return destination; + } + // Handle relative paths + const basePath = '/docs'; + return destination.startsWith('/') + ? `${request.nextUrl.origin}${basePath}${destination}` + : `${request.nextUrl.origin}${basePath}/${destination}`; +} export function middleware(request: NextRequest) { - const path = request.nextUrl.pathname - const pathWithoutBase = path.replace('/docs', '') - - // Handle base redirects from redirects.ts - const redirect = updatedRedirectsData.find((r: any) => r.source === pathWithoutBase) - if (redirect) { - return NextResponse.redirect(createRedirectUrl(request, redirect.destination, path)) - } - // Handle version without slug - const versionOnlyMatch = pathWithoutBase.match(/^\/v\/(\d+\.\d+)$/) - if (versionOnlyMatch) { - return NextResponse.redirect(`https://${versionOnlyMatch[1]}.sourcegraph.com/`) - } - // Handle version-specific redirects - if (pathWithoutBase.startsWith(`/v/${docsConfig.DOCS_LATEST_VERSION}/`)) { - return NextResponse.redirect(createRedirectUrl( - request, - `https://sourcegraph.com/docs/:slug*`, - pathWithoutBase - )) - } - if (pathWithoutBase.startsWith(`/@${docsConfig.DOCS_LATEST_VERSION}/`)) { - return NextResponse.redirect(createRedirectUrl( - request, - `https://sourcegraph.com/docs/:slug*`, - pathWithoutBase - )) - } - const versionMatch = pathWithoutBase.match(/^\/v\/(\d+\.\d+)\/(.*)/) - if (versionMatch) { - return NextResponse.redirect(createRedirectUrl( - request, - 'https://:version.sourcegraph.com/:slug*', - pathWithoutBase - )) - } - const atVersionMatch = pathWithoutBase.match(/^\/@(\d+\.\d+)\/(.*)/) - if (atVersionMatch) { - return NextResponse.redirect(createRedirectUrl( - request, - 'https://:version.sourcegraph.com/:slug*', - pathWithoutBase - )) - } - if (pathWithoutBase === '/changelog.rss') - return NextResponse.redirect(createRedirectUrl(request, '/technical-changelog.rss', path)) - - return NextResponse.next() + const path = request.nextUrl.pathname; + const pathWithoutBase = path.replace('/docs', ''); + + // Handle base redirects from redirects.ts + const redirect = updatedRedirectsData.find( + (r: any) => r.source === pathWithoutBase + ); + if (redirect) { + return NextResponse.redirect( + createRedirectUrl(request, redirect.destination, path) + ); + } + + // Handle latest version without path - redirect to main docs + const latestVersionOnlyMatch = pathWithoutBase.match( + `^\/(?:v\/|@)${docsConfig.DOCS_LATEST_VERSION}\/?$` + ); + if (latestVersionOnlyMatch) { + return NextResponse.redirect(`https://sourcegraph.com/docs`); + } + + // Handle version without slug - both /v/X.Y and @X.Y formats (for non-latest versions) + const versionOnlyMatch = pathWithoutBase.match( + /^\/(?:v\/|@)(\d+\.\d+)\/?$/ + ); + if ( + versionOnlyMatch && + versionOnlyMatch[1] !== docsConfig.DOCS_LATEST_VERSION + ) { + return NextResponse.redirect( + `https://${versionOnlyMatch[1]}.sourcegraph.com/` + ); + } + + // Handle version-specific redirects + if (pathWithoutBase.startsWith(`/v/${docsConfig.DOCS_LATEST_VERSION}/`)) { + return NextResponse.redirect( + createRedirectUrl( + request, + `https://sourcegraph.com/docs/:slug*`, + pathWithoutBase + ) + ); + } + if (pathWithoutBase.startsWith(`/@${docsConfig.DOCS_LATEST_VERSION}/`)) { + return NextResponse.redirect( + createRedirectUrl( + request, + `https://sourcegraph.com/docs/:slug*`, + pathWithoutBase + ) + ); + } + const versionMatch = pathWithoutBase.match(/^\/v\/(\d+\.\d+)\/(.*)/); + if (versionMatch) { + return NextResponse.redirect( + createRedirectUrl( + request, + 'https://:version.sourcegraph.com/:slug*', + pathWithoutBase + ) + ); + } + const atVersionMatch = pathWithoutBase.match(/^\/@(\d+\.\d+)\/(.*)/); + + if (atVersionMatch) { + return NextResponse.redirect( + createRedirectUrl( + request, + 'https://:version.sourcegraph.com/:slug*', + pathWithoutBase + ) + ); + } + + if (pathWithoutBase === '/changelog.rss') + return NextResponse.redirect( + createRedirectUrl(request, '/technical-changelog.rss', path) + ); + + return NextResponse.next(); } export const config = { - matcher: [ - '/((?!api|_next/static|_next/image|assets|favicon.ico|sw.js).*)', - ], -} + matcher: ['/((?!api|_next/static|_next/image|assets|favicon.ico|sw.js).*)'] +};