question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Middleware (12.2.3) causing infinite redirect/refresh of interior page routes

See original GitHub issue

Verify 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:closed
  • Created a year ago
  • Reactions:4
  • Comments:8 (3 by maintainers)

github_iconTop GitHub Comments

2reactions
ludovicoserrani-nautescommented, Jul 29, 2022

@ijjk I had the same issue as @wadehammes and it works for me in the latest canary 12.2.4-canary.8. Thank you!

2reactions
ijjkcommented, Jul 28, 2022

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!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Infinite redirection using middleware - Stack Overflow
The infinite loop is from trying to redirect to the login route, and always hitting this code: else if (to.meta.middleware == "guest") {...
Read more >
How to Fix The ERR_TOO_MANY_REDIRECTS Error - Kinsta
The ERR_TOO_MANY_REDIRECTS error is pretty much what it sounds like: something is causing too many redirects, sending your website into an infinite ......
Read more >
Routing in ASP.NET Core - Microsoft Learn
Routing is responsible for matching incoming HTTP requests and dispatching those requests to the app's executable endpoints.
Read more >
Shallow Routing - Next.js
When shallow routing is used with middleware it will not ensure the new page matches the current page like previously done without middleware....
Read more >
The router Property - Nuxt
You can do so via the routeNameSplitter option in your configuration file. Imagine we have the page file pages/posts/_id.vue . Nuxt will generate...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found