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

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

Closed
AlbertSabate opened this issue Oct 13, 2023 · 3 comments · Fixed by #280
Closed

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

AlbertSabate opened this issue Oct 13, 2023 · 3 comments · Fixed by #280

Comments

@AlbertSabate
Copy link
Contributor

AlbertSabate commented Oct 13, 2023

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,
        };
    }
@khuezy
Copy link
Contributor

khuezy commented Oct 13, 2023

Hi thanks for the investigation and fix, can you put up a PR and add some test cases around this?

@AlbertSabate
Copy link
Contributor Author

Ey @khuezy yeah I'm on it. I'll update here when ready.

@AlbertSabate
Copy link
Contributor Author

PR ready for review: #280

khuezy pushed a commit that referenced this issue Oct 16, 2023
…#280)

* TrailingSlash using rewrite for a fetch call results on infinite loop
Fixes: #279
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants