Skip to content

overwrite redirect SSG meta.status to 200 for RSC requests #80379

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

Conversation

gaojude
Copy link
Contributor

@gaojude gaojude commented Jun 10, 2025

For a static route that simply returns a redirect:

export default function Page() {
  redirect("/about");
}

the SSG generates a .meta file for the route at build time, that looks like:

{
  "status": 307,
  "headers": {
    "location": "/about"
  }
}

On next start, if a request matches this route, the status code is retrieved from the file and returned to the response. This is perfectly fine for DOC requests. However, if the request is an RSC request, its RSC payload should have already encoded the redirect instruction:

1:"$Sreact.fragment"
2:I[657,[],""]
3:I[8597,[],""]
5:I[5975,[],"OutletBoundary"]
8:I[4429,[],"AsyncMetadataOutlet"]
a:I[5975,[],"ViewportBoundary"]
c:I[5975,[],"MetadataBoundary"]
e:I[1363,[],""]
0:{"P":null,"b":"gelhztYnmFGzccJ4F6F4T","p":"","c":["","rsc-redirect"],"i":false,"f":[[["",{"children":["rsc-redirect",{"children":["__PAGE__",{}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[null,["$","html",null,{"lang":"en","children":["$","body",null,{"children":["$","$L2",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L3",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}]]}],{"children":["rsc-redirect",["$","$1","c",{"children":[null,["$","$L2",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L3",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["__PAGE__",["$","$1","c",{"children":["$L4",null,["$","$L5",null,{"children":["$L6","$L7",["$","$L8",null,{"promise":"$@9"}]]}]]}],{},null,false]},null,false]},null,false],["$","$1","h",{"children":[null,["$","$1","0db7ba866b0656c433aa56ad545d5b104626108ev",{"children":[["$","$La",null,{"children":"$Lb"}],null]}],["$","$Lc",null,{"children":"$Ld"}]]}],false]],"m":"$undefined","G":["$e","$undefined"],"s":false,"S":true}
4:E{"digest":"NEXT_REDIRECT;replace;/about;307;"}
f:"$Sreact.suspense"
10:I[4429,[],"AsyncMetadata"]
d:["$","div",null,{"hidden":true,"children":["$","$f",null,{"fallback":null,"children":["$","$L10",null,{"promise":"$@11"}]}]}]
7:null
b:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]
6:null
9:{"metadata":[],"error":null,"digest":"$undefined"}
11:{"metadata":"$9:metadata","error":null,"digest":"$undefined"}

Specifically,

4:E{"digest":"NEXT_REDIRECT;replace;/about;307;"}

Hence, it would be fine to simply return 200 status code.

There are two motivations for this change:

  1. This new behaviour is consistent with Next.js apps hosted on Vercel. (I.e., it returns 200 for static RSC even if the meta.status = 307)
  2. 307 redirect on RSC payload is an obstacle to enabling RSC validation

Existing E2E tests should cover this change.

@ijjk ijjk added created-by: Next.js team PRs by the Next.js team. type: next labels Jun 10, 2025
Copy link
Contributor Author

gaojude commented Jun 10, 2025

@gaojude gaojude marked this pull request as ready for review June 10, 2025 18:03
@gaojude gaojude force-pushed the 06-10-overwrite_redirect_ssg_meta.status_to_200_for_rsc_requests branch from 5a0baa4 to fec157b Compare June 10, 2025 22:07
@gaojude gaojude closed this Jun 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants