Code Monkey home page Code Monkey logo

Comments (7)

lukemorton avatar lukemorton commented on September 23, 2024 3

@igorxmath Good point about refreshing. A refresh after the 404 does indeed show the right page.

Only consistent fix I’ve found is to start redirect URL with a dot “./location” instead of “/location” or fully qualified domain, e.g. “https://example.com/location”. That’s if redirecting to another location on the same domain. I have not tested cross domain redirects after a server action.

from next.js.

jericopulvera avatar jericopulvera commented on September 23, 2024 1

We encountered an issue when redirecting from nested path. e.g /users/create to /users

the fix is to add another dot similar to how you import file from a parent directory.

redirect("../users")

another example from /users/1/edit to /users

redirect("../../users")

from next.js.

EgorKrasno avatar EgorKrasno commented on September 23, 2024 1

I was also having this issue, it looks like when you redirect from a server action it sets the host header to just localhost:3000. Which breaks the middleware rewriting logic.

I was able to fix this in middleware by catching redirects originating from a server action and pulling the subdomain from x-forwarded-host and the redirect path from x-action-redirect and just rebuilding the URL.

const action = req.headers.get('x-action-redirect');
if (process.env.NODE_ENV === 'production' && action) {
    const forwardedHost = req.headers.get('x-forwarded-host')?.split('.')[0];
    const newUrl = `https://localhost:3000/${forwardedHost}/${action.split('/').pop()}`;
    return NextResponse.rewrite(newUrl);
}

from next.js.

FroeMic avatar FroeMic commented on September 23, 2024 1

@EgorKrasno I faced a similar issue, using a server-action to log-in users in multi-tenant app that handles subdomains via rewrites in a middleware. Your answer put me on the right path.

I adapted you code, right at the top of the middleware function. I found that the x-action-redirect property contained the desired url, which allowed me tom avoid some of the splitting.

export default async function middleware(req: NextRequest) {
  let host = req.headers.get("host")!;
  let url = new URL(req.url);

 //------------------------------------------------------------
 // Relevant code starts here
 //-----------------------------------------------------------
  
const action = req.headers.get("x-action-redirect");
const forwardedHost = req.headers.get("x-forwarded-host")!;
  if (
    process.env.NODE_ENV === "production" &&
    host == "localhost:3000" &&
    forwardedHost &&
    action
  ) {
    host = forwardedHost;
    url = new URL(action, req.url);
  }

 //------------------------------------------------------------
 // Relevant code ends here
 //-----------------------------------------------------------`

  // Get hostname of request (e.g. demo.vercel.pub, demo.localhost:3000)
  const hostname = getTenantHostname(host);
  const subdomain = getTenantSubdomain(host);

  const searchParams = url.searchParams.toString();
  // Get the pathname of the request (e.g. /, /about, /blog/first-post)
  const path = `${url.pathname}${
    searchParams.length > 0 ? `?${searchParams}` : ""
  }`;

  // Deal with reserved subdomains (e.g. admin.domain.tld)
  if (hostname == `admin.${env.PUBLIC_ROOT_DOMAIN}`) {
    return NextResponse.rewrite(
      new URL(`/admin${path === "/" ? "" : path}`, req.url),
    );
  }

  // Deal with the case when there is NO subdomain; i.e. redirect to a landing page
  if (hostname === "localhost:3000" || hostname === env.PUBLIC_ROOT_DOMAIN) {
    return NextResponse.rewrite(
      new URL(`/home${path === "/" ? "" : path}`, req.url),
    );
  }

  // rewrite everything else to `/[subdomain]/[slug] dynamic route
  return NextResponse.rewrite(new URL(`/${subdomain}${path}`, req.url));
}

For completeness, here are the other two custom functions:

export function getTenantHostname(host: string) {
  // host e.g.: calw.localhost:3000, calw.climate-hub.eu, climae-hub.eu, 11---preview.calw.climate-hub.eu

  let hostname = host.replace(".localhost:3000", `.${env.PUBLIC_ROOT_DOMAIN}`); // the "replace only works if there is a subdomain present"

  // Deal with deployment previews
  if (hostname.includes("---preview.")) {
    hostname = `${hostname.split("---preview.")[1]}`;
  }

  return hostname;
}

export function getTenantSubdomain(host: string) {
  const subdomain = getTenantHostname(host);
  return subdomain.replace(`.${env.PUBLIC_ROOT_DOMAIN}`, "");
}

Thank you for your answer! Hope this helps someone.

from next.js.

igorxmath avatar igorxmath commented on September 23, 2024

I'm having the same issue with rewrites in middleware. Every time a redirect is called with server actions, Next.js shows a 404 page. However, when I reload the browser, the page loads correctly.

from next.js.

jmarbutt avatar jmarbutt commented on September 23, 2024

I am having this issue also. Was this working in previous versions? I feel like it was but in a recent update this changed. I am curious if anyone else has noticed that also?

I use redirect all over the place in my app with subdomain routing so I hate having to go into every one of my server actions to fix this but have for the time being.

from next.js.

RahulBirCodes avatar RahulBirCodes commented on September 23, 2024

Are you guys getting responses from your server actions? I just get undefined because the middleware rewrites the calls server actions do under the hood but if I exclude it from the middleware then redirects don't work lol

from next.js.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.