Middleware (12.2.3) causing infinite redirect/refresh of interior page routes
See original GitHub issueVerify canary release
- I verified that the issue exists in the latest Next.js canary release
Provide environment information
Operating System: Platform: linux Arch: x64 Version: #1 SMP Wed Mar 2 00:30:59 UTC 2022 Binaries: Node: 16.15.0 npm: 8.5.5 Yarn: 1.22.19 pnpm: 7.5.0 Relevant packages: next: 12.2.3 eslint-config-next: 12.2.3 react: 18.2.0 react-dom: 18.2.0
What browser are you using? (if relevant)
Firefox
How are you deploying your application? (if relevant)
Vercel
Describe the Bug
Since Middleware 12.2 stable, I have had issues with redirects happening infinitely for interior page routes (home path is fine). I have tried to strip away everything and I still get infinite redirects with just only the cookie setting option.
https://user-images.githubusercontent.com/222170/180466999-7ef7e685-958e-4a2a-a847-6ab0a2265853.mp4
Here is my middleware file in case any of you sleuths spot an error on my end:
import isbot from "isbot";
import { type NextRequest, NextResponse, userAgent } from "next/server";
import {
fetchFeatureFlag,
MarketingHomeAbTestVariantValues,
} from "src/api/fetchFeatureFlag";
import { Environments } from "src/interfaces/common.interfaces";
import { CONSTANTS } from "src/utils/constants";
import { v4 as uuid } from "uuid";
const PUBLIC_FILE = /\.(.*)$/;
isbot.extend(["/DatadogSynthetics/"]);
export async function middleware(request: NextRequest) {
const nextPage = NextResponse.next();
const { url } = request;
const { ua } = userAgent(request);
const { pathname, basePath, origin, locale, search } = request.nextUrl;
const homeUrl = new URL(`${basePath}/`, origin).toString();
const expires = new Date(Date.now() + 2592000000); // one month expiration
if (
pathname.startsWith("/_next") || // exclude Next.js internals
pathname.startsWith("/api") || // exclude all API routes
pathname.startsWith("/static") || // exclude static files
PUBLIC_FILE.test(pathname) // exclude all files in the public folder
) {
return nextPage;
}
// Setup rhFeatureFlagUserId
// this will run on all paths of the site, no matter
// where a visitor enters, to ensure it gets set up
let rhFeatureFlagUserId = request.cookies.get(
CONSTANTS.RH_FEATURE_FLAG_USER_ID_COOKIE
);
if (!rhFeatureFlagUserId) {
rhFeatureFlagUserId = `rh_${uuid()}`;
nextPage.cookies.set(
CONSTANTS.RH_FEATURE_FLAG_USER_ID_COOKIE,
rhFeatureFlagUserId,
{
expires,
sameSite: "strict",
}
);
}
// If pathname is not lowercase, redirect
if (pathname !== pathname.toLowerCase()) {
const lowercaseRedirect = NextResponse.redirect(
new URL(`${pathname.toLowerCase()}${search}`, url)
);
lowercaseRedirect.cookies.set(
CONSTANTS.RH_FEATURE_FLAG_USER_ID_COOKIE,
rhFeatureFlagUserId,
{
expires,
sameSite: "strict",
}
);
return lowercaseRedirect;
}
// Redirect any direct traffic to our test variant back to home page
if (
process.env.ENVIRONMENT === Environments.Production &&
pathname.startsWith("/variant-home")
) {
const redirect = NextResponse.redirect(homeUrl);
redirect.cookies.set(
CONSTANTS.RH_FEATURE_FLAG_USER_ID_COOKIE,
rhFeatureFlagUserId,
{
expires,
sameSite: "strict",
}
);
return redirect;
}
// Homepage AB Test Setup
if (pathname === CONSTANTS.HOME_ROUTE && !isbot(ua)) {
// Launch Darkly flag: marketing-home-ab-test-multiple-variants
// If flag is off, defaults to "original" (control home page)
const marketingHomeAbTestVariantSlug = await fetchFeatureFlag<string>({
featureFlagUserId: rhFeatureFlagUserId,
flag: "marketing-home-ab-test-multiple-variants",
defaultValue: MarketingHomeAbTestVariantValues.Original,
});
if (marketingHomeAbTestVariantSlug) {
const testPage =
marketingHomeAbTestVariantSlug !==
MarketingHomeAbTestVariantValues.Original
? NextResponse.rewrite(
new URL(
`${basePath}/${locale}/${marketingHomeAbTestVariantSlug}${search}`,
origin
).toString()
)
: NextResponse.next();
// Make sure we add our feature flag user id to cookies
// since we reset the NextResponse to a new const
testPage.cookies.set(
CONSTANTS.RH_FEATURE_FLAG_USER_ID_COOKIE,
rhFeatureFlagUserId,
{
expires,
sameSite: "strict",
}
);
testPage.cookies.set(
CONSTANTS.RH_HOME_PAGE_TEST_COOKIE,
marketingHomeAbTestVariantSlug,
{
expires,
sameSite: "strict",
}
);
return testPage;
}
return nextPage;
}
return nextPage;
}
Expected Behavior
12.1.6 nested middleware works fine (same setup is used there, just in 12.1.6 format https://www.gotrhythm.com). My expectations are that it should not cause an infinite redirect as you see in the video above with 12.2.3.
Link to reproduction
https://rhythm-marketing-l1rj1cudn-gotrhythm.vercel.app/
To Reproduce
Create a middleware file with a redirect.
Issue Analytics
- State:
- Created a year ago
- Reactions:4
- Comments:8 (3 by maintainers)
Top GitHub Comments
@ijjk I had the same issue as @wadehammes and it works for me in the latest canary
12.2.4-canary.8
. Thank you!Circling back here this sounds related to https://github.com/vercel/next.js/issues/39049 which has been updated in
v12.2.4-canary.3
of Next.js, please update and give it a try!