diff --git a/packages/gitbook/src/lib/context.ts b/packages/gitbook/src/lib/context.ts index 162ea03a15..3f3bcda039 100644 --- a/packages/gitbook/src/lib/context.ts +++ b/packages/gitbook/src/lib/context.ts @@ -24,7 +24,8 @@ import { notFound } from 'next/navigation'; import { assert } from 'ts-essentials'; import { GITBOOK_URL } from './env'; import { type ImageResizer, createImageResizer } from './images'; -import { type GitBookLinker, createLinker } from './links'; +import { type GitBookLinker, createLinker, joinPaths } from './links'; +import { getPreviewRequestIdentifier, isPreviewRequest } from './preview'; /** * Data about the site URL. Provided by the middleware. @@ -165,7 +166,17 @@ export function getBaseContext(input: { // Create link in the same format for links to other sites/sections. linker.toLinkForContent = (rawURL: string) => { const urlObject = new URL(rawURL); - return `/url/${urlObject.host}${urlObject.pathname}${urlObject.search}${urlObject.hash}`; + + // For preview requests make sure we include the preview/site as part of the site URL + const pathname = isPreviewRequest(siteURL) + ? joinPaths( + `preview/${getPreviewRequestIdentifier(siteURL)}`, + urlObject.pathname.includes(siteURLData.siteBasePath) + ? urlObject.pathname.replace(siteURLData.siteBasePath, '') + : urlObject.pathname + ) + : `${urlObject.host}${urlObject.pathname}`; + return `/url/${pathname}${urlObject.search}${urlObject.hash}`; }; } diff --git a/packages/gitbook/src/lib/links.ts b/packages/gitbook/src/lib/links.ts index 3825cf492c..32c29bd10b 100644 --- a/packages/gitbook/src/lib/links.ts +++ b/packages/gitbook/src/lib/links.ts @@ -166,7 +166,7 @@ export function linkerWithOtherSpaceBasePath( return newLinker; } -function joinPaths(prefix: string, path: string): string { +export function joinPaths(prefix: string, path: string): string { const prefixPath = prefix.endsWith('/') ? prefix : `${prefix}/`; const suffixPath = path.startsWith('/') ? path.slice(1) : path; const pathWithoutTrailingSlash = removeTrailingSlash(prefixPath + suffixPath); diff --git a/packages/gitbook/src/middleware.ts b/packages/gitbook/src/middleware.ts index 45f9cef308..7705072177 100644 --- a/packages/gitbook/src/middleware.ts +++ b/packages/gitbook/src/middleware.ts @@ -25,6 +25,8 @@ import { } from '@/lib/visitors'; import { serveResizedImage } from '@/routes/image'; import type { SiteURLData } from './lib/context'; +import { joinPaths } from './lib/links'; +import { getPreviewRequestIdentifier, isPreviewRequest } from './lib/preview'; export const config = { matcher: [ '/((?!_next/static|_next/image|~gitbook/static|~gitbook/revalidate|~gitbook/monitoring|~scalar/proxy).*)', @@ -180,10 +182,15 @@ async function serveSiteRoutes(requestURL: URL, request: NextRequest) { // during development and testing in 'url' mode. if (mode === 'url') { const urlObject = new URL(siteURLData.redirect); - contentRedirect = new URL( - `/url/${urlObject.host}${urlObject.pathname}${urlObject.search}`, - request.url - ); + + // For preview requests make sure we include the preview/site as part of the site URL + const pathname = isPreviewRequest(siteRequestURL) + ? joinPaths( + `preview/${getPreviewRequestIdentifier(siteRequestURL)}`, + urlObject.pathname + ) + : `${urlObject.host}${urlObject.pathname}`; + contentRedirect = new URL(`/url/${pathname}${urlObject.search}`, request.url); } // Keep the same search params as the original request @@ -332,10 +339,10 @@ async function serveSiteRoutes(requestURL: URL, request: NextRequest) { }; // For https://preview/ requests, - if (siteRequestURL.hostname === 'preview') { + if (isPreviewRequest(siteRequestURL)) { return serveWithQueryAPIToken( // We scope the API token to the site ID. - `${siteRequestURL.hostname}/${requestURL.pathname.slice(1).split('/')[0]}`, + `preview/${getPreviewRequestIdentifier(siteRequestURL)}`, request, withAPIToken );