sst / open-next

Open source Next.js serverless adapter
https://open-next.js.org
MIT License
3.7k stars 111 forks source link

Leading slash redirects not working for next server actions (but does work locally) #396

Open citypaul opened 3 months ago

citypaul commented 3 months ago

I spent some time trying to figure out why a redirect from a server action wasn't working. What made this more difficult was the fact that it works just fine locally, but when I deploy it to AWS the redirect does not work if there's a leading slash.

Absolute URLs work just fine, and removing the leading slash makes it work.

I've reduced this down to literally just a redirect in the server action itself, and the issue seems consistent for me.

If you have a server action inside it with literally nothing more than:

import { redirect } from "next/navigation";

export const myServerAction = () => {
   redirect("/dashboard");
}

This doesn't work when deployed, but does locally.

But if I do:

import { redirect } from "next/navigation";

export const myServerAction = () => {
   redirect("dashboard");
}

It's working just fine.

I'm using SST 2.41.2. All routes are based on the app dir. I'm on next 14.1.4.

khuezy commented 3 months ago

Can you reproduce this locally via standalone output? Just trying to verify if this is a next standalone issue or a bug somewhere in open-next redirect.

davidjoy commented 2 months ago

Hi there - I'm seeing this issue as well. I tried the above suggestion w/r/t 'standalone mode':

I just tried building (npm run build) my Next.js site with output: 'standalone' in the next.config.js and running it locally with node .next/standalone/server.js. I'm calling a server action from a client-side rendered form's action handler (at a /sign-in route). I put a redirect to redirect('/update-password'); (a valid route on my app) at the top of my server action and commented out the rest - the redirect works fine locally in standalone mode and redirects to /update-password without issue.

I'm using SST v2.41.4 and its default v2.3.7 version of open-next.

When I see this in a production AWS environment, it manifests for me as:

  1. A 500 error response in the browser to the form submission to /sign-in, with a response body of {"message":null} - this is odd because I don't have any responses that look like that in my app.
  2. I was able to see console.log statements in the CloudWatch logs all the way up to when I'm calling redirect, so nothing else in the server action is throwing as far as I can tell. My redirect is not in a try/catch. ✅
  3. I see a X-Amzn-Errortype: InternalFailure header on that response.
  4. I turned on OPEN_NEXT_DEBUG and I can see a server response with a statusCode: 303 header and an x-action-redirect: /update-password header in the CloudWatch logs - I don't see that response in my client anywhere.
  5. I don't see anything going 'wrong' in the CloudWatch logs, though. No 500s, no errors, and I'm not sure why that might not be making it back to the client.

If I modify the redirect to use a full, absolute CloudFront URL for my distribution (redirect('https://blahcloudfrontyblah.cloudfront.net/update-password');) it works fine in production. I'd consider this a workaround, though.

conico974 commented 1 month ago

Tested this in V3, it works just fine there for me. If you guys can confirm in your app or provide a reproduction.

Derek-X-Wang commented 1 month ago

Hi @conico974,

Here is a reproducible demo for this issue. https://github.com/Derek-X-Wang/open-next-issue-396

SST v2.41.5 Next.js v14.2.3 OpenNext v2.3.8

The demo is created via

pnpm create next-app
pnpm create sst

To start local dev

pnpm sst dev
pnpm run dev

Deploy staging env

pnpm sst deploy --stage staging

my staging demo: https://d11lu0si5g9k8u.cloudfront.net/

Local Env: both server actions(withLeadingSlash and withoutLeadingSlash) work. Staging Env: withLeadingSlash doesn't work, return 500. withoutLeadingSlash work as @citypaul described.

server action in https://github.com/Derek-X-Wang/open-next-issue-396/blob/main/src/actions/example.ts

I haven't try with open-next V3. I use open-next indirectly via SST. Is it possible to use different version of open-next with SST?

khuezy commented 1 month ago

You'll need to apply this patch until the PR is merged: https://github.com/sst/sst/pull/3567 You could try to deploy via ion - the redirect might be fixed in v3.