Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

12.2.6-canary.10 displaying JSON in browser instead of building page html #40241

Closed
1 task done
wadehammes opened this issue Sep 6, 2022 · 9 comments · Fixed by #40333
Closed
1 task done

12.2.6-canary.10 displaying JSON in browser instead of building page html #40241

wadehammes opened this issue Sep 6, 2022 · 9 comments · Fixed by #40333
Labels
bug Issue was opened via the bug report template. please add a complete reproduction The issue lacks information for further investigation

Comments

@wadehammes
Copy link

Verify canary release

  • I verified that the issue exists in the latest Next.js canary release

Provide environment information

Operating System:
Platform: darwin
Arch: arm64
Version: Darwin Kernel Version 21.6.0: Wed Aug 10 14:28:23 PDT 2022; root:xnu-8020.141.5~2/RELEASE_ARM64_T6000
Binaries:
Node: 16.15.0
npm: 8.5.5
Yarn: 1.22.19
pnpm: N/A
Relevant packages:
next: 12.2.6-canary.9
eslint-config-next: 12.2.6-canary.9
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

When deploying to Vercel with the latest canary, visiting pages will sometimes flash the styled output and then display the page JSON in the browser:

Screenshot 2022-09-05 at 10 18 40 PM

Expected Behavior

Page shoudl rendered with styled HTML.

Link to reproduction

https://rhythm-marketing-git-update-next1226-gotrhythm.vercel.app/

To Reproduce

Standard Next.js setup with i18n and basic middleware rewrite usage.

@wadehammes wadehammes added the bug Issue was opened via the bug report template. label Sep 6, 2022
@wadehammes wadehammes changed the title 12.2.6-canary.9 displaying JSON in browser instead of building page html 12.2.6-canary.10 displaying JSON in browser instead of building page html Sep 6, 2022
@balazsorban44
Copy link
Member

Some browser extensions (e.g. JSON viewer) might cause this issue. Can you verify it's not the case? (I.e. try opening the page in a different browser/incognito, making sure the extension is disabled). I cannot look at your deployment because it's password protected, but having a look at the code would be more useful anyway. Can you link your repository/reproduction, please? 🙏

@balazsorban44 balazsorban44 added the please add a complete reproduction The issue lacks information for further investigation label Sep 6, 2022
@wadehammes
Copy link
Author

wadehammes commented Sep 6, 2022

Unfortunately it is all private and I do not have time to complete a reproduction today. I've never seen this happen before in my time using Next.js. Current stable of our site is running 12.2.5 with no issues.

I'm seeing this happen in all browsers, private (no extensions) and regular. Seems to shift to JSON view if I do a hard refresh (cmd+shift+r)

@balazsorban44

@wadehammes
Copy link
Author

I could paste some files here if it helps?

next.config.js

const { withSentryConfig } = require("@sentry/nextjs");

const sentryWebpackPluginOptions = {
  // Additional config options for the Sentry Webpack plugin. Keep in mind that
  // the following options are set automatically, and overriding them is not
  // recommended:
  //   release, url, org, project, authToken, configFile, stripPrefix,
  //   urlPrefix, include, ignore

  silent: true, // Suppresses all logs
  // For all available options, see:
  // https://github.com/getsentry/sentry-webpack-plugin#options.
};

const withTM = require("next-transpile-modules")([
  "@mui/material",
  "@mui/system",
]);

module.exports = withSentryConfig(
  withTM(
    {
      reactStrictMode: true,
      productionBrowserSourceMaps: true,
      outputFileTracing: false,
      swcMinify: true,
      compiler: {
        // ssr and displayName are configured by default
        styledComponents: true,
        reactRemoveProperties: false,
      },
      images: {
        domains: [
          "images.ctfassets.net",
          "assets.ctfassets.net",
          "videos.ctfassets.net",
          "assets.zappyride.com",
        ],
      },
      i18n: {
        locales: ["en", "es"],
        defaultLocale: "en",
      },
      sentry: {
        disableClientWebpackPlugin: true,
        disableServerWebpackPlugin: true,
      },
      env: {
        CONTENTFUL_SPACE_ID: process.env.CONTENTFUL_SPACE_ID,
        CONTENTFUL_API_TOKEN: process.env.CONTENTFUL_API_TOKEN,
        CONTENTFUL_PREVIEW_TOKEN: process.env.CONTENTFUL_PREVIEW_TOKEN,
        CONTENTFUL_PREVIEW_SECRET: process.env.CONTENTFUL_PREVIEW_SECRET,
        ENVIRONMENT: process.env.ENVIRONMENT,
        GA_TRACKING_ID: process.env.GA_TRACKING_ID,
        GA_GTM_PREVIEW_ENV: process.env.GA_GTM_PREVIEW_ENV,
        GA_GTM_AUTH: process.env.GA_GTM_AUTH,
        NEXT_PUBLIC_SENTRY_DSN: process.env.NEXT_PUBLIC_SENTRY_DSN,
        SEGMENT_ANALYTICS_KEY: process.env.SEGMENT_ANALYTICS_KEY,
        SENTRY_TRACES_SAMPLE_RATE: process.env.SENTRY_TRACES_SAMPLE_RATE,
        SENTRY_AUTH_TOKEN: process.env.SENTRY_AUTH_TOKEN,
        VERCEL_GITHUB_COMMIT_SHA: process.env.VERCEL_GITHUB_COMMIT_SHA,
        FULLSTORY_ORG_ID: process.env.FULLSTORY_ORG_ID,
        API_SECRET: process.env.API_SECRET,
        EMBED_SOCIAL_API_KEY: process.env.EMBED_SOCIAL_API_KEY,
        VERCEL_TEAM_ID: process.env.VERCEL_TEAM_ID,
        VERCEL_API_TOKEN: process.env.VERCEL_API_TOKEN,
        SMARTY_STREETS_WEBKEY: process.env.SMARTY_STREETS_WEBKEY,
        SMARTY_STREETS_AUTH_ID: process.env.SMARTY_STREETS_AUTH_ID,
        SMARTY_STREETS_AUTH_TOKEN: process.env.SMARTY_STREETS_AUTH_TOKEN,
        ZAPPY_RIDE_API_AUTH_KEY: process.env.ZAPPY_RIDE_API_AUTH_KEY,
        LAUNCH_DARKLY_CLIENT_ID: process.env.LAUNCH_DARKLY_CLIENT_ID,
      },
      webpack: (config, options) => {
        if (options.isServer && options.nextRuntime !== "nodejs") return config;

        config.module.rules.push({
          test: /\.svg$/,
          use: ["@svgr/webpack"],
        });

        return config;
      },
      async redirects() {
        if (process.env.ENVIRONMENT === "production") {
          return [
            ...productionRedirects,
            ...sharedRedirects,
            ...oldCampaignRedirects,
          ];
        } else {
          return [...sharedRedirects, ...oldCampaignRedirects];
        }
      },
      async headers() {
        return [
          {
            source: "/",
            headers: [
              {
                key: "Cache-Control",
                value: "s-maxage=1, stale-while-revalidate",
              },
              ...securityHeaders,
            ],
          },
          {
            source: "/:path*",
            headers: [
              {
                key: "Cache-Control",
                value: "s-maxage=1, stale-while-revalidate",
              },
              ...securityHeaders,
            ],
          },
          {
            source: "/fonts/averta-font/(.*)",
            headers: [
              {
                key: "Cache-Control",
                value: "public, max-age=31536000, stale-while-revalidate",
              },
              ...securityHeaders,
            ],
          },
          {
            source: "/fonts/fontface.css",
            headers: [
              {
                key: "Cache-Control",
                value: "public, max-age=31536000, stale-while-revalidate",
              },
              ...securityHeaders,
            ],
          },
        ];
      },
    },
    sentryWebpackPluginOptions
  )
);

// Redirect test and home slug pages on Production
const sources = [
  "/:parent(test-page.*)",
  "/:parent(home.*)",
  "/partner/:slug(test-page.*)",
  "/affiliate/:slug(test-page.*)",
  "/lp/:slug(test-page.*)",
  "/page-preview",
  "/deployments",
  "/hello",
];

const productionRedirects = sources.map((source) => ({
  source,
  destination: "/",
  permanent: true,
}));

const oldCampaignUrls = [
  "/bingo",
  "/breathe",
  "/hardtospell-2",
  "/visa",
  "/cinemark",
];

const oldCampaignRedirects = oldCampaignUrls.map((source) => ({
  source,
  destination: "/",
  permanent: true,
}));

// Redirects various lp directories to home page since they have no page
const lpSources = ["/partner", "/affiliate", "/lp"];

const lpRedirects = lpSources.map((source) => ({
  source,
  destination: "/",
  permanent: true,
}));

const error404Redirects = [
  {
    // 301 Redirect /eswelcome 404
    source: "/eswelcome",
    destination: "/es/welcome",
    permanent: true,
  },
  {
    // 301 Redirect /eswelcome 404
    source: "/es/eswelcome",
    destination: "/es/welcome",
    permanent: true,
  },
  {
    // 301 Redirect /hc/en-us 404
    source: "/hc/en-us",
    destination: "/",
    permanent: true,
  },
  {
    source: "/summer-email",
    destination: "/lp/email-summer",
    permanent: true,
  },
  {
    source: "/email-summer",
    destination: "/lp/email-summer",
    permanent: true,
  },
  {
    source: "/lp/solar-buyback-12",
    destination: "/rooftop-solar-buyback-plan",
    permanent: true,
  },
  {
    source: "/about/and",
    destination: "/about",
    permanent: true,
  },
  {
    source: "/about/a",
    destination: "/about",
    permanent: true,
  },
];

// Redirects needed for both Production and Staging/Development
const sharedRedirects = [
  {
    // 301 Redirect ElectricityPlans page to new affiliate url
    source: "/ep",
    destination: "/affiliate/ep",
    permanent: true,
  },
  {
    // 301 Redirect original simple header page to new lp url
    source: "/texas-sh",
    destination: "/lp/texas-sh",
    permanent: true,
  },
  {
    // 301 Redirect Support pages
    source: "/support",
    destination: "https://support.gotrhythm.com",
    permanent: true,
  },
  {
    // 301 Redirect register pages
    source: "/register",
    destination: "https://app.gotrhythm.com/sign-up?rcid=default",
    permanent: true,
  },
  {
    // 301 Redirect login page
    source: "/login",
    destination: "https://app.gotrhythm.com/sign-in",
    permanent: true,
  },
  {
    // 301 Redirect login page
    source: "/sign-in",
    destination: "https://app.gotrhythm.com/sign-in",
    permanent: true,
  },
  {
    // 301 Redirect login page
    source: "/account",
    destination: "https://app.gotrhythm.com/sign-in",
    permanent: true,
  },
  {
    // 301 Redirect login page
    source: "/myaccount",
    destination: "https://app.gotrhythm.com/sign-in",
    permanent: true,
  },
  {
    // 301 Redirect login page
    source: "/my-account",
    destination: "https://app.gotrhythm.com/sign-in",
    permanent: true,
  },
  {
    // 301 Redirect register pages
    source: "/sign-up",
    destination: "https://app.gotrhythm.com/sign-up?rcid=default",
    permanent: true,
  },
  {
    // 301 Redirect register pages
    source: "/sign-up/plans",
    destination: "https://app.gotrhythm.com/sign-up?rcid=default",
    permanent: true,
  },
  {
    // 301 Redirect /payments 404
    source: "/payments",
    destination: "https://app.gotrhythm.com/sign-in",
    permanent: true,
  },
  {
    // 301 Redirect /payments 404
    source: "/pay-bill",
    destination: "https://app.gotrhythm.com/sign-in",
    permanent: true,
  },
  {
    // 301 Redirect Earth Day
    source: "/lp/texas-earth-day",
    destination: "/electricity/texas",
    permanent: true,
  },
  {
    // 301 Redirect Earth Day
    source: "/lp/fb-earth-day",
    destination: "/electricity/texas",
    permanent: true,
  },
  {
    // 301 Redirect /reviews 404
    source: "/reviews",
    destination: "/about/reviews",
    permanent: true,
  },
  {
    // 301 Redirect /chapman-ranch
    source: "/chapman-ranch",
    destination: "/chapman-ranch-wind-energy-plans-texas",
    permanent: true,
  },
  {
    // 301 Redirect /solar
    source: "/solar",
    destination: "/solar-electricity-plans",
    permanent: true,
  },
  {
    // 301 Redirect /solar-buyback
    source: "/solar-buyback",
    destination: "/rooftop-solar-buyback-plan",
    permanent: true,
  },
  {
    // 301 Redirect /careers
    source: "/careers",
    destination: "/about/careers",
    permanent: true,
  },
  {
    // 301 Redirect /jobs
    source: "/jobs",
    destination: "/about/careers",
    permanent: true,
  },
  {
    // 301 Redirect /rewards 404
    source: "/why-rhythm/rewards",
    destination: "/rewards",
    permanent: true,
  },
  {
    // Redirect /purchase to /purchase/new-vehicles
    source: "/ev/purchase",
    destination: "/ev/purchase/new-vehicles",
    permanent: true,
  },
  {
    // Redirect /terms to /terms-of-use
    source: "/terms",
    destination: "/terms-of-use",
    permanent: true,
  },
  {
    // Redirect /ev/power to /electric-vehicle-plans
    source: "/ev/power",
    destination: "/electric-vehicle-plans",
    permanent: true,
  },
  {
    // Redirect old plans page to new plans overview
    source: "/why-rhythm/electricity-plans",
    destination: "/plans-overview",
    permanent: true,
  },
  {
    // Redirect old home solar buyback to new rooftop solar buyback
    source: "/solar-buyback-plan",
    destination: "/rooftop-solar-buyback-plan",
    permanent: true,
  },
  {
    // Redirect all /electricity SEO pages (including city pages) to new /texas-electricity
    source: "/electricity(.*)",
    destination: "/texas-electricity",
    permanent: true,
  },
  {
    // Redirect all /vs competitor pages to /compare
    source: "/vs(.*)",
    destination: "/compare-texas-electricity-providers",
    permanent: true,
  },
  {
    // Redirect all /mymove to home
    source: "/mymove",
    destination: "/",
    permanent: true,
  },
  {
    source: "/secure",
    destination:
      "/secure2022?utm_source=external-mktg&utm_medium=DM&utm_campaign=ADM_SecureMover_07_2022&utm_content=secure-move-july2022&utm_term=20220705&rcid=simplisafe",
    permanent: true,
  },
  {
    // Redirect /simply-move to new simply-move with query and rcid param
    source: "/simply-move",
    destination:
      "/simply-move2022?rcid=mover-promo-200&utm_content=simplymove-july2022&utm_term=20220705&utm_source=external-mktg&utm_medium=DM&utm_campaign=ADM_SimplyMove200_07_2022",
    permanent: true,
  },
  {
    // Redirect /movers to new movers2022 with query and rcid param
    source: "/movers",
    destination:
      "/movers2022?utm_source=external-mktg&utm_medium=MyMoveDigital&utm_campaign=AWM_MyMoveDigital_07_2022&utm_content=mymove-july2022&utm_term=20220701&rcid=simplisafe",
    permanent: true,
  },
  ...error404Redirects,
  ...lpRedirects,
];

// https://securityheaders.com
const scriptSrc = [
  "'self'",
  "'unsafe-eval'",
  "'unsafe-inline'",
  "*.youtube.com",
  "*.ads-twitter.com",
  "*.twitter.com",
  "*.instagram.com",
  "*.ctfassets.net",
  "*.fullstory.com",
  "*.zdassets.com",
  "*.segment.com",
  "*.facebook.net",
  "*.nextdoor.com",
  "*.tvsquared.com",
  "*.doubleclick.net",
  "*.adsrvr.org",
  "*.bing.com",
  "*.google.com",
  "*.google-analytics.com",
  "*.googletagmanager.com",
  "*.googleadservices.com",
  "*.googleusercontent.com",
  "polyfill.io",
  "*.vercel-insights.com",
  "*.vercel.app",
  "embedsocial.com",
  "*.abtasty.com",
  "*.smooch.io",
  "*.mypurecloud.com",
  "*.cloudfront.net",
  "*.cobrowse.io",
  "*.redditstatic.com",
  "*.clarity.ms",
  "aa.trkn.us",
  "*.hotjar.com",
  "*.adnxs.com",
  "*.shop.pe",
  "shop.pe",
  "addshoppers.s3.amazonaws.com",
  "cdn.id5-sync.com",
  "action.dstillery.com",
  "action.media6degrees.com",
];

const ContentSecurityPolicy = `
  default-src 'self';
  script-src ${scriptSrc.join(" ")};
  child-src *.youtube.com *.google.com *.twitter.com *.facebook.com *.adsrvr.org *.doubleclick.net embedsocial.com *.abtasty.com;
  style-src 'self' 'unsafe-inline' *.googleapis.com *.google.com *.googletagmanager.com embedsocial.com *.abtasty.com;
  img-src * blob: data: *.ctfassets.net *.fbsbx.com *.googleusercontent.com *.abtasty.com smart-pixl.com *.fullstory.com;
  object-src * blob: data:;
  media-src 'self' *.zdassets.com *.ctfassets.net *.abtasty.com;
  connect-src *;
  frame-src * 'self' blob: data: *.ctfassets.net *.abtasty.com;
  font-src 'self' data: fonts.gstatic.com *.abtasty.com *.cloudflare.com;
  worker-src 'self' *.vercel.app;
  manifest-src 'self' *.vercel.app;
`;

const setAccessControlOrigin = () => {
  if (process.env.ENVIRONMENT === "production") {
    return "https://www.gotrhythm.com";
  } else if (process.env.ENVIRONMENT === "staging") {
    return "https://www.staging.gotrhythm.com";
  } else {
    return "http://localhost:1337";
  }
};

const securityHeaders = [
  // https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
  {
    key: "Content-Security-Policy",
    value: ContentSecurityPolicy.replace(/\n/g, ""),
  },
  // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy
  {
    key: "Referrer-Policy",
    value: "strict-origin-when-cross-origin",
  },
  // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
  {
    key: "X-Frame-Options",
    value: "SAMEORIGIN",
  },
  // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options
  {
    key: "X-Content-Type-Options",
    value: "nosniff",
  },
  // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-DNS-Prefetch-Control
  {
    key: "X-DNS-Prefetch-Control",
    value: "on",
  },
  // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security
  {
    key: "Strict-Transport-Security",
    value: "max-age=31536000; includeSubDomains; preload",
  },
  // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Feature-Policy
  {
    key: "Permissions-Policy",
    value: "camera=(), microphone=(), geolocation=(), interest-cohort=()",
  },
  {
    key: "Access-Control-Allow-Origin",
    value: setAccessControlOrigin(),
  },
  {
    key: "Vary",
    value: "Origin",
  },
];

middleware.ts

import isbot from "isbot";
import { type NextRequest, NextResponse, userAgent } from "next/server";
import {
  fetchFeatureFlag,
  MarketingHomeAbTestVariantValues,
} from "src/api/fetchFeatureFlag";
import { CONSTANTS } from "src/utils/constants";
import { v4 as uuid } from "uuid";

isbot.extend(["/DatadogSynthetics/"]);

const PUBLIC_FILE = /\.(.*)$/;

export async function middleware(request: NextRequest) {
  const nextPage = NextResponse.next();

  const { url, headers } = request;
  const { ua } = userAgent(request);
  const { pathname, basePath, origin, locale, search } = request.nextUrl;

  const expires = new Date(Date.now() + 2592000000); // one month expiration

  const homeUrl = new URL(`${basePath}/${locale}${search}`, origin).toString();
  const twoMonthsFreePlanUrl = new URL(
    `${basePath}/${locale}/${CONSTANTS.TWO_MONTHS_FREE_PLAN_SLUG}${search}`,
    origin
  );

  const isTwoMonthsFreePlanAdLander =
    pathname.includes(
      CONSTANTS.TWO_MONTHS_FREE_PLAN_FREE_INFLATION_RELIEF_LANDER
    ) || pathname.includes(CONSTANTS.TWO_MONTHS_FREE_PLAN_FREE_IS_GOOD_LANDER);

  const referer = headers.get("Referer") || "";

  const isNavigatingFromTwoMonthsFreePlanAdLander =
    referer.includes(CONSTANTS.TWO_MONTHS_FREE_PLAN_FREE_IS_GOOD_LANDER) ||
    referer.includes(
      CONSTANTS.TWO_MONTHS_FREE_PLAN_FREE_INFLATION_RELIEF_LANDER
    );

  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 home test variant back to home page
  if (pathname.startsWith("/variant-home")) {
    const homeRedirect = NextResponse.redirect(homeUrl);

    homeRedirect.cookies.set(
      CONSTANTS.RH_FEATURE_FLAG_USER_ID_COOKIE,
      rhFeatureFlagUserId,
      {
        expires,
        sameSite: "strict",
      }
    );

    return homeRedirect;
  }

  // Homepage AB Test Setup
  if (
    pathname === CONSTANTS.HOME_ROUTE &&
    !isbot(ua) &&
    !isNavigatingFromTwoMonthsFreePlanAdLander
  ) {
    // 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 homeTestPage =
        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
      homeTestPage.cookies.set(
        CONSTANTS.RH_FEATURE_FLAG_USER_ID_COOKIE,
        rhFeatureFlagUserId,
        {
          expires,
          sameSite: "strict",
        }
      );

      homeTestPage.cookies.set(
        CONSTANTS.RH_HOME_PAGE_TEST_COOKIE,
        marketingHomeAbTestVariantSlug,
        {
          expires,
          sameSite: "strict",
        }
      );

      return homeTestPage;
    }

    return nextPage;
  }

  // Redirect any direct traffic to our two months free plan test variant back to control page
  if (pathname.startsWith(`/${CONSTANTS.TWO_MONTHS_FREE_PLAN_VARIANT_SLUG}`)) {
    const twoMonthsFreePlanRedirect =
      NextResponse.redirect(twoMonthsFreePlanUrl);

    twoMonthsFreePlanRedirect.cookies.set(
      CONSTANTS.RH_FEATURE_FLAG_USER_ID_COOKIE,
      rhFeatureFlagUserId,
      {
        expires,
        sameSite: "strict",
      }
    );

    return twoMonthsFreePlanRedirect;
  }

  // Two Free Months AB Test Setup
  if (
    pathname.startsWith(`/${CONSTANTS.TWO_MONTHS_FREE_PLAN_SLUG}`) &&
    !isTwoMonthsFreePlanAdLander &&
    !isbot(ua)
  ) {
    const homePageTestSlug = await fetchFeatureFlag<string>({
      featureFlagUserId: rhFeatureFlagUserId,
      flag: "marketing-home-ab-test-multiple-variants",
      defaultValue: MarketingHomeAbTestVariantValues.Original,
    });

    if (homePageTestSlug === MarketingHomeAbTestVariantValues.Original) {
      // Launch Darkly flag: marketing-two-free-month-plan
      // If flag is off, defaults to "two-months-free-plan"
      const marketingTwoMonthsFreePlanSlug = await fetchFeatureFlag<string>({
        featureFlagUserId: rhFeatureFlagUserId,
        flag: "marketing-two-free-month-plan",
        defaultValue: CONSTANTS.TWO_MONTHS_FREE_PLAN_SLUG,
      });

      if (marketingTwoMonthsFreePlanSlug) {
        const twoMonthsFreeTestPage =
          marketingTwoMonthsFreePlanSlug !== CONSTANTS.TWO_MONTHS_FREE_PLAN_SLUG
            ? NextResponse.rewrite(
                new URL(
                  `${basePath}/${locale}/${marketingTwoMonthsFreePlanSlug}${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
        twoMonthsFreeTestPage.cookies.set(
          CONSTANTS.RH_FEATURE_FLAG_USER_ID_COOKIE,
          rhFeatureFlagUserId,
          {
            expires,
            sameSite: "strict",
          }
        );

        twoMonthsFreeTestPage.cookies.set(
          CONSTANTS.RH_TWO_MONTHS_FREE_PLAN_COOKIE,
          marketingTwoMonthsFreePlanSlug,
          {
            expires,
            sameSite: "strict",
          }
        );

        return twoMonthsFreeTestPage;
      }

      return nextPage;
    }

    if (homePageTestSlug === CONSTANTS.RH_HOME_PAGE_VARIANT_B_SLUG) {
      const twoMonthsFreePlanVariantBPage = NextResponse.rewrite(
        new URL(
          `${basePath}/${locale}/${CONSTANTS.TWO_MONTHS_FREE_PLAN_VARIANT_SLUG}${search}`,
          origin
        ).toString()
      );

      // Make sure we add our feature flag user id to cookies
      // since we reset the NextResponse to a new const
      twoMonthsFreePlanVariantBPage.cookies.set(
        CONSTANTS.RH_FEATURE_FLAG_USER_ID_COOKIE,
        rhFeatureFlagUserId,
        {
          expires,
          sameSite: "strict",
        }
      );

      twoMonthsFreePlanVariantBPage.cookies.set(
        CONSTANTS.RH_TWO_MONTHS_FREE_PLAN_COOKIE,
        CONSTANTS.TWO_MONTHS_FREE_PLAN_VARIANT_SLUG,
        {
          expires,
          sameSite: "strict",
        }
      );

      return twoMonthsFreePlanVariantBPage;
    }

    return nextPage;
  }

  return nextPage;
}

These are the only files where I could see something causing this, although like I said, 12.2.5 works fine (as seen on https://www.gotrhythm.com) running these same files.

@balazsorban44
Copy link
Member

balazsorban44 commented Sep 7, 2022

Could you verify which canary caused the issue first? Sounds like candidates are 12.2.6-canary.0 up to 12.2.6-canary.10. If it's a bug, that would help us track down the exact PR that introduced this.

Also, just to confirm:

When deploying to Vercel with the latest canary

So does this only happen when deployed, or in next dev/next build && next start also?

@jakejarvis
Copy link
Contributor

jakejarvis commented Sep 7, 2022

Experiencing this on 12.2.6-canary.10 as well — will follow up with a reproduction.

edit: in the meantime, https://jarvis-edvwwdw43-jakejarvis.vercel.app/projects/
edit 2: URL above just fixed itself. hmm...
edit 3: I've traced it backwards and it looks like something introduced in canary.7 is causing this — possibly #39902 or #40076? Still investigating. :)

Screen Shot 2022-09-07 at 2 55 43 PM

jakejarvis added a commit to jakejarvis/jarv.is that referenced this issue Sep 7, 2022
ijjk added a commit that referenced this issue Sep 7, 2022
This temporarily reverts the refactor while we investigate
#40241 further.

Reverts #39902
jakejarvis added a commit to jakejarvis/jarv.is that referenced this issue Sep 7, 2022
@sdornan
Copy link
Contributor

sdornan commented Sep 7, 2022

This issue still seems to occur with canary.11.

@wadehammes
Copy link
Author

@jakejarvis thanks for getting to this before I had a chance today!

ijjk added a commit that referenced this issue Sep 7, 2022
This unreverts #40328 as it wasn't
the cause for #40241 like
initially suspected and the actual fix has been included here as well
with regression test.

Fixes: #40241

## Bug

- [x] Related issues linked using `fixes #number`
- [x] Integration tests added
- [ ] Errors have helpful link attached, see `contributing.md`
@ijjk
Copy link
Member

ijjk commented Sep 8, 2022

Hi, this should now be patched in v12.2.6-canary.12of Next.js

@github-actions
Copy link
Contributor

github-actions bot commented Oct 8, 2022

This closed issue has been automatically locked because it had no new activity for a month. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Oct 8, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Issue was opened via the bug report template. please add a complete reproduction The issue lacks information for further investigation
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants