Skip to content

Commit

Permalink
[sitecore-jss-nextjs] [Redirects] Fix for Redirects related to x-mid…
Browse files Browse the repository at this point in the history
…dleware-next Header #SXA-6564 (#1899)
  • Loading branch information
sc-ruslanmatkovskyi authored Aug 29, 2024
1 parent 8d68f79 commit ca06445
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 18 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ Our versioning strategy is as follows:

### 🧹 Chores

## 22.1.2

### 🐛 Bug Fixes

* `[sitecore-jss-nextjs]` Resolved an issue with redirects that was caused by the x-middleware-next header in Next.js. This header prevented the flow from being interrupted properly, resulting in redirects not functioning correctly in certain cases. ([#1899](https://github.com/Sitecore/jss/pull/1899))

## 22.1.1

### 🎉 New Features & Improvements
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1430,6 +1430,62 @@ describe('RedirectsMiddleware', () => {
});
});

it('should remove x-middleware-next header and redirect 301', async () => {
const siteName = 'foo';
const res = NextResponse.redirect('http://localhost:3000/found', {});
res.headers.set('x-middleware-next', '1');
res.cookies.set('sc_site', siteName);
const req = createRequest({
nextUrl: {
href: 'http://localhost:3000/not-found',
pathname: '/not-found',
locale: 'en',
search: '',
origin: 'http://localhost:3000',
clone() {
return Object.assign({}, req.nextUrl);
},
},
});

const { middleware, fetchRedirects, siteResolver } = createMiddleware({
pattern: 'not-found',
target: '/found',
redirectType: REDIRECT_TYPE_301,
isQueryStringPreserved: true,
locale: 'en',
});

const expected = NextResponse.redirect('http://localhost:3000/found', {
...res,
status: 301,
headers: {},
});

const finalRes = await middleware.getHandler()(req, res);

validateDebugLog('redirects middleware start: %o', {
hostname: 'foo.net',
language: 'en',
pathname: '/not-found',
});

validateEndMessageDebugLog('redirects middleware end in %dms: %o', {
headers: {
location: 'http://localhost:3000/found',
'set-cookie': 'sc_site=foo; Path=/',
},
redirected: false,
status: 301,
url: '',
});

expect(siteResolver.getByHost).not.called.to.equal(true);
expect(siteResolver.getByName).to.be.calledWith(siteName);
expect(fetchRedirects).to.be.calledWith(siteName);
expect(finalRes.status).to.equal(expected.status);
});

describe('should redirect to normalized path when nextjs specific "path" query string parameter is provided', () => {
it('should return 301 redirect', async () => {
const setCookies = () => {};
Expand Down
54 changes: 36 additions & 18 deletions packages/sitecore-jss-nextjs/src/middleware/redirects-middleware.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import regexParser from 'regex-parser';
import { NextResponse, NextRequest } from 'next/server';
import { debug } from '@sitecore-jss/sitecore-jss';
import {
RedirectInfo,
GraphQLRedirectsService,
GraphQLRedirectsServiceConfig,
REDIRECT_TYPE_301,
REDIRECT_TYPE_302,
REDIRECT_TYPE_SERVER_TRANSFER,
RedirectInfo,
SiteInfo,
} from '@sitecore-jss/sitecore-jss/site';
import { debug } from '@sitecore-jss/sitecore-jss';
import { NextRequest, NextResponse } from 'next/server';
import regexParser from 'regex-parser';
import { MiddlewareBase, MiddlewareBaseConfig } from './middleware';

const REGEXP_CONTEXT_SITE_LANG = new RegExp(/\$siteLang/, 'i');
Expand Down Expand Up @@ -147,20 +147,12 @@ export class RedirectsMiddleware extends MiddlewareBase {

/** return Response redirect with http code of redirect type **/
switch (existsRedirect.redirectType) {
case REDIRECT_TYPE_301:
return NextResponse.redirect(redirectUrl, {
...res,
status: 301,
statusText: 'Moved Permanently',
headers: res?.headers,
});
case REDIRECT_TYPE_302:
return NextResponse.redirect(redirectUrl, {
...res,
status: 302,
statusText: 'Found',
headers: res?.headers,
});
case REDIRECT_TYPE_301: {
return this.createRedirectResponse(redirectUrl, res, 301, 'Moved Permanently');
}
case REDIRECT_TYPE_302: {
return this.createRedirectResponse(redirectUrl, res, 302, 'Found');
}
case REDIRECT_TYPE_SERVER_TRANSFER: {
return this.rewrite(redirectUrl, req, res || NextResponse.next());
}
Expand Down Expand Up @@ -267,4 +259,30 @@ export class RedirectsMiddleware extends MiddlewareBase {

return new URL(`${url.pathname}`, url.origin);
}

/**
* Helper function to create a redirect response and remove the x-middleware-next header.
* @param {string} url The URL to redirect to.
* @param {Response} res The response object.
* @param {number} status The HTTP status code of the redirect.
* @param {string} statusText The status text of the redirect.
* @returns {NextResponse<unknown>} The redirect response.
*/
private createRedirectResponse(
url: string,
res: Response | undefined,
status: number,
statusText: string
): NextResponse {
const redirect = NextResponse.redirect(url, {
...(res || {}),
status,
statusText,
headers: res?.headers,
});
if (res?.headers) {
redirect.headers.delete('x-middleware-next');
}
return redirect;
}
}

0 comments on commit ca06445

Please sign in to comment.