vercel / platforms

A full-stack Next.js app with multi-tenancy and custom domain support. Built with Next.js App Router and the Vercel Domains API.
https://app.vercel.pub
5.72k stars 763 forks source link

server actions redirect issue #408

Open jericopulvera opened 5 months ago

jericopulvera commented 5 months ago

I have a login page in a [domain]/login/page.tsx that calls a server action.

  revalidatePath("/");
  redirect('/?test=test');

  // tried also
  // redirect('http://tenant1.localhost:3000?test=test');

In the login page of a site e.g: http://tenant1.localhost:3000/login

when you successfully logged in it does redirect to http://tenant1.localhost:3000/ but the page shown is the home page of the platform not the tenant but when you refresh manually you get the home page of the tenant.

I have added a console.log in the middleware.

export default async function middleware(req: NextRequest) {
  const url = req.nextUrl;

  // Get hostname of request (e.g. demo.vercel.pub, demo.localhost:3000)
  let hostname = req.headers
    .get("host")!
    .replace(".localhost:3000", `.${clientEnv.NEXT_PUBLIC_ROOT_DOMAIN}`);

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

  console.log({ hostname, path });
  //...
}  

Same log output for redirect("/?test=test") and redirect('http://tenant1.localhost:3000?test=test')

{ hostname: 'org1.localhost:3000', path: '/login' }
{ hostname: 'localhost:3000', path: '/?test=test' }
 POST /login 303 in 168ms
{ hostname: 'org1.localhost:3000', path: '/?test=test' }

so it looks like the issue is that redirect in server actions does not care about the subdomain.

Only tested this locally on next v14.2.3

jericopulvera commented 5 months ago

Looks to be related to this issue https://github.com/vercel/next.js/issues/65893#issue-2303215033

jericopulvera commented 5 months ago

does not make sense but the solution here amazingly worked for me. https://github.com/vercel/next.js/issues/65893#issuecomment-2132081500

redirect("./");
jericopulvera commented 2 months ago

does not make sense but the solution here amazingly worked for me. vercel/next.js#65893 (comment)

redirect("./");

This solution is flawed when the server action is triggered from a differently nested path you'll be redirected to the current path which would result in 404.

e.g: logout action has redirect('./login')

if logout action is triggered at /profile or / you're redirected to /login but if logout action is triggered at /profile/activity you're redirected to /profile/login.

better solution I found is to use .get("x-forwarded-host") instead of .get("host")

// Get hostname of request (e.g. demo.vercel.pub, demo.localhost:3000)
  const hostname = req.headers
    .get("x-forwarded-host")!
    .replace(".localhost:3000", `.${clientEnv.NEXT_PUBLIC_ROOT_DOMAIN}`);