vercel / next.js

The React Framework
https://nextjs.org
MIT License
127k stars 26.99k forks source link

`redirect` should return 307 for SSR `app` routes with Edge runtime #46437

Open leebenson opened 1 year ago

leebenson commented 1 year ago

Verify canary release

Provide environment information

Operating System:
  Platform: darwin
  Arch: x64
  Version: Darwin Kernel Version 22.3.0: Mon Jan 30 20:42:11 PST 2023; root:xnu-8792.81.3~2/RELEASE_X86_64
Binaries:
  Node: 16.17.1
  npm: 8.15.0
  Yarn: 1.22.17
  pnpm: N/A
Relevant packages:
  next: 13.2.2-canary.1
  eslint-config-next: N/A
  react: 18.2.0
  react-dom: 18.2.0

Which area(s) of Next.js are affected? (leave empty if unsure)

App directory (appDir: true), Routing (next/router, next/navigation, next/link)

Link to the code that reproduces this issue

https://github.com/leebenson/nextjs-ssr-redirect-issue

To Reproduce

Run npm run dev and curl -I localhost:3000/redirect

Describe the Bug

Motivated by https://github.com/vercel/next.js/discussions/45746

redirect correctly returns a 307 when used in Server Components in the app folder with the Node.JS runtime, but returns 200 when set to experimental-edge.

Example...

next.config.js

/** @type {import('next').NextConfig} */
const nextConfig = {
  experimental: {
    appDir: true,
    runtime: "experimental-edge",
  },
};

module.exports = nextConfig;

src/app/redirect/page.tsx

import { redirect } from "next/navigation";

async function shouldRedirect() {
  redirect("/");
}

export default async function ShouldRedirect() {
  await shouldRedirect();

  return <h1>Should never show</h1>;
}

Then start the server with npm run dev and curl -I localhost:3000/redirect.

Notice the 200 response:

HTTP/1.1 200 OK
content-type: text/html; charset=utf-8
vary: RSC, Next-Router-State-Tree, Next-Router-Prefetch
x-edge-runtime: 1
x-powered-by: Next.js
Date: Sun, 26 Feb 2023 12:51:39 GMT
Connection: keep-alive
Keep-Alive: timeout=5

If runtime: "experimental-edge" is removed from next.config.js, re-executing curl -I localhost:3000/redirect produces:

HTTP/1.1 307 Temporary Redirect
Vary: RSC, Next-Router-State-Tree, Next-Router-Prefetch, Accept-Encoding
Cache-Control: no-store, must-revalidate
X-Powered-By: Next.js
Content-Type: text/html; charset=utf-8
Date: Sun, 26 Feb 2023 12:55:12 GMT
Connection: keep-alive
Keep-Alive: timeout=5

⚠️: The HTML response is present in both runtimes. I would expect the server to respond with an 'empty' 307.

Expected Behavior

I'd expect a 307 response to be consistent in all runtimes.

I would also expect the response body to be empty and not contain the HTML bootstrapping.

Which browser are you using? (if relevant)

No response

How are you deploying your application? (if relevant)

npm run dev

ayhanap commented 1 year ago

It also returns 200 if the page is behind a vs . Must be some internal hydration thing.

remorses commented 1 year ago

This is expected behaviour, when using streaming your page will render after the headers and status have already been sent, which means that status will be 200 and redirect will be done using http-equiv meta tag https://developers.google.com/search/docs/crawling-indexing/301-redirects#metarefresh