Skip to content

TrailingSlash using rewrite for a fetch call results on infinite loop #279

Closed
@AlbertSabate

Description

@AlbertSabate

Hello team,

I was struggling with an infinite loop and blaming the cache on CloudFront. However, after some hours of research, the issue is with the trailing slash.

Explanation step by step:

  1. I'm using Mixpanel to keep track of the users.
  2. I created a rewrite to next.config.js to avoid ad-blockers blocking the request to Mixpanel made by the client (using only the browser version).
  3. Mixpanel client will send the request as ${url}/track/ -> In my case, I will make a rewrite from /mp/:slug to their API.
  4. Notice the last slash on track/ as that is the crucial part here.
  5. Because I do not have set trailingslash=true, the redirect will be to ${url}/track instead of to the end API URL.
  6. Loop

My investigation arrived here. I'm still researching why this creates an infinite loop because, from my understanding, it should double redirect to not trailing slash and then to the final API URL.

In localhost, the setup is working correctly.

To give it a shot, it will be as easy as installing mixpanel-browser and initialise with a rewrite, for example:

rewrites: () => [
    {
      source: '/mp/decide',
      destination: 'https://decide.mixpanel.com/decide',
    },
    {
      source: '/mp/:slug',
      // use "api-eu.mixpanel.com" if you need to use EU servers
      destination: 'https://api-eu.mixpanel.com/:slug',
    },
  ],

I tried enabling trailing slash, and then it worked as expected.
However, when using search parameters, something seems off.
Result when accessing to:
-> https://xxxx.cloudfront.net/mp/track?verbose=1&ip=1&_=1697202041851
<- https://xxxx.cloudfront.net/mp/track?verbose=1&ip=1&_=1697202041851///////////////////////////////////////////////////////////////////////////////////////////////
(Notice the loop)

Expectation:

  • No infinite loops
  • Does fetch need to handle trailing slash? Disable it if it is a fetch request.
  • Handle properly search params

UPDATE
I found something more.
On the file [Line: 176 && 191]: https://github.com/sst/open-next/blob/main/packages/open-next/src/adapters/routing/matcher.ts
If the URL contains search parameters, then that is when the infinite loop happens. I think considering search params on this redirect will fix the issue.

SOLUTION
On the file [Line: 176 && 191]: https://github.com/sst/open-next/blob/main/packages/open-next/src/adapters/routing/matcher.ts

const headersLocation = event.url.split('?');
    if (NextConfig.trailingSlash &&
        !event.rawPath.endsWith("/") &&
        !event.headers["x-nextjs-data"]) {
        return {
            type: event.type,
            statusCode: 308,
            headers: {
                Location: headersLocation[0] + "/" + (headersLocation[1] ? "?" + headersLocation[1] : ""),
            },
            body: "",
            isBase64Encoded: false,
        };
        // eslint-disable-next-line sonarjs/elseif-without-else
    }
    else if (!NextConfig.trailingSlash &&
        event.rawPath.endsWith("/") &&
        event.rawPath !== "/") {
        return {
            type: event.type,
            statusCode: 308,
            headers: {
                Location: headersLocation[0].replace(/\/$/, "") + (headersLocation[1] ? "?" + headersLocation[1] : ""),
            },
            body: "",
            isBase64Encoded: false,
        };
    }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions