diff --git a/.changeset/orange-shirts-relax.md b/.changeset/orange-shirts-relax.md new file mode 100644 index 000000000..081f48d2f --- /dev/null +++ b/.changeset/orange-shirts-relax.md @@ -0,0 +1,5 @@ +--- +"@headstartwp/next": patch +--- + +Ensure query string is appended to URL rewrite/redirect in middleware diff --git a/packages/next/src/middlewares/__tests__/appMiddleware.ts b/packages/next/src/middlewares/__tests__/appMiddleware.ts index 11cf6dc73..8afc5d0a2 100644 --- a/packages/next/src/middlewares/__tests__/appMiddleware.ts +++ b/packages/next/src/middlewares/__tests__/appMiddleware.ts @@ -305,6 +305,51 @@ describe('appMiddleware', () => { expect(res.headers.get('x-headstartwp-locale')).toBe('pt'); }); + it('[multisite] supports query strings in App and Pages router', async () => { + setHeadstartWPConfig({ + sites: [ + { + sourceUrl: 'http://testwp.com', + hostUrl: 'http://test.com', + }, + { + sourceUrl: 'http://testwp2.com', + hostUrl: 'http://test2.com', + }, + { + sourceUrl: 'http://testwp2.com/en', + hostUrl: 'http://test2.com', + }, + ], + }); + + // App Router + let req = new NextRequest('http://test2.com/post-name?s=search-slug', { + method: 'GET', + }); + + req.headers.set('host', 'test2.com'); + + let res = await AppMiddleware(req, { appRouter: true }); + + expect(res.headers.get('x-middleware-rewrite')).toBe( + 'http://test2.com/test2.com/post-name?s=search-slug', + ); + + // Pages Router + req = new NextRequest('http://test2.com/post-name?s=search-slug', { + method: 'GET', + }); + + req.headers.set('host', 'test2.com'); + + res = await AppMiddleware(req, { appRouter: false }); + + expect(res.headers.get('x-middleware-rewrite')).toBe( + 'http://test2.com/_sites/test2.com/post-name?s=search-slug', + ); + }); + it('[polylang] supports locales with app router', async () => { setHeadstartWPConfig({ sourceUrl: 'http://testwp.com', @@ -343,6 +388,16 @@ describe('appMiddleware', () => { res = await AppMiddleware(req, { appRouter: true }); expect(res.headers.get('x-middleware-rewrite')).toBe('http://test.com/en/post-name'); + + // add default locale with a query string + req = new NextRequest('http://test.com/post-name?s=query', { + method: 'GET', + }); + + res = await AppMiddleware(req, { appRouter: true }); + expect(res.headers.get('x-middleware-rewrite')).toBe( + 'http://test.com/en/post-name?s=query', + ); }); it('[polylang no locale detection] supports locales with app router', async () => { diff --git a/packages/next/src/middlewares/appMidleware.ts b/packages/next/src/middlewares/appMidleware.ts index 86fc3312a..94effaebf 100644 --- a/packages/next/src/middlewares/appMidleware.ts +++ b/packages/next/src/middlewares/appMidleware.ts @@ -93,7 +93,7 @@ export async function AppMiddleware( options: AppMidlewareOptions = { appRouter: false }, ) { let response = NextResponse.next(); - const { pathname } = req.nextUrl; + const { pathname, searchParams } = req.nextUrl; if (isStaticAssetRequest(req) || isInternalRequest(req)) { return response; @@ -120,6 +120,9 @@ export async function AppMiddleware( const site = getSiteByHost(hostname, !hasPolylangIntegration ? locale : undefined); const isMultisiteRequest = site !== null && typeof site.sourceUrl !== 'undefined'; + // ensure we re-add the query string when rewriting/redirecing + const queryString = Array.from(searchParams.keys()).length ? `?${searchParams.toString()}` : ''; + const { redirectStrategy, sourceUrl, @@ -161,7 +164,7 @@ export async function AppMiddleware( shouldRedirect = true; const pathNameWithoutLocale = pathname.replace(`/${locale}`, ''); response = NextResponse.redirect( - new URL(pathNameWithoutLocale, req.url.replace(`/${locale}`, '')), + new URL(pathNameWithoutLocale + queryString, req.url.replace(`/${locale}`, '')), ); } // if we detected a non-default locale, there isn't a supported locale in the URL already @@ -175,14 +178,17 @@ export async function AppMiddleware( ) { shouldRedirect = true; response = NextResponse.redirect( - new URL(`/${locale}${pathname.startsWith('/') ? '' : '/'}${pathname}`, req.url), + new URL( + `/${locale}${pathname.startsWith('/') ? '' : '/'}${pathname}${queryString}`, + req.url, + ), ); } // nothing else and there's not a locale in path then rewrite to add default locale else if (pathnameIsMissingLocale && !isValidLocale(firstPathSlice)) { response = NextResponse.rewrite( new URL( - `/${defaultAppRouterLocale}${pathname.startsWith('/') ? '' : '/'}${pathname}`, + `/${defaultAppRouterLocale}${pathname.startsWith('/') ? '' : '/'}${pathname}${queryString}`, req.url, ), ); @@ -191,10 +197,10 @@ export async function AppMiddleware( if (isMultisiteRequest && !shouldRedirect) { const hostNameOrSlug = site.slug || hostname; - const pagesRouterRewrite = `/_sites/${hostNameOrSlug}${pathname}`; + const pagesRouterRewrite = `/_sites/${hostNameOrSlug}${pathname}${queryString}`; const appRouterRewrite = locale - ? `/${locale}/${hostNameOrSlug}${pathname.replace(`/${locale}`, '')}` - : `/${hostNameOrSlug}${pathname}`; + ? `/${locale}/${hostNameOrSlug}${pathname.replace(`/${locale}`, '')}${queryString}` + : `/${hostNameOrSlug}${pathname}${queryString}`; response = NextResponse.rewrite( new URL(options.appRouter ? appRouterRewrite : pagesRouterRewrite, req.nextUrl),