Handle getStaticProps.redirect (vercel/turbo#3497)

This PR adds support for returning `redirect: { destination, permanent,
statusCode }` from `getStaticProps`.
This commit is contained in:
Alex Kirszenberg 2023-01-27 14:39:10 +01:00 committed by GitHub
parent 0cf02c89ed
commit 822bb5d15c
3 changed files with 52 additions and 14 deletions

View file

@ -8,6 +8,8 @@ import "@vercel/turbopack-next/internal/shims";
import type { IncomingMessage, ServerResponse } from "node:http";
import { renderToHTML, RenderOpts } from "next/dist/server/render";
import { getRedirectStatus } from "next/dist/lib/redirect-status";
import { PERMANENT_REDIRECT_STATUS } from "next/dist/shared/lib/constants";
import type { BuildManifest } from "next/dist/server/get-page-files";
import type { ReactLoadableManifest } from "next/dist/server/load-components";
@ -27,7 +29,7 @@ type IpcOutgoingMessage =
| {
type: "response";
statusCode: number;
contentType: string;
headers: Array<[string, string]>;
body: string;
}
| { type: "rewrite"; path: string };
@ -197,7 +199,7 @@ export default function startHandler({
renderOpts
);
// This is set when `getStaticProps` returns `notFound: true`.
// Set when `getStaticProps` returns `notFound: true`.
const isNotFound = (renderOpts as any).isNotFound;
if (isNotFound) {
@ -206,7 +208,7 @@ export default function startHandler({
type: "response",
statusCode,
body: '{"notFound":true}',
contentType: MIME_APPLICATION_JAVASCRIPT,
headers: [["Content-Type", MIME_APPLICATION_JAVASCRIPT]],
};
}
@ -218,13 +220,49 @@ export default function startHandler({
};
}
// Set when `getStaticProps` returns `redirect: { destination, permanent, statusCode }`.
const isRedirect = (renderOpts as any).isRedirect;
if (isRedirect && !isDataReq) {
const pageProps = (renderOpts as any).pageData.pageProps;
const redirect = {
destination: pageProps.__N_REDIRECT,
statusCode: pageProps.__N_REDIRECT_STATUS,
basePath: pageProps.__N_REDIRECT_BASE_PATH,
};
const statusCode = getRedirectStatus(redirect);
// TODO(alexkirsz) Handle basePath.
// if (
// basePath &&
// redirect.basePath !== false &&
// redirect.destination.startsWith("/")
// ) {
// redirect.destination = `${basePath}${redirect.destination}`;
// }
const headers: Array<[string, string]> = [
["Location", redirect.destination],
];
if (statusCode === PERMANENT_REDIRECT_STATUS) {
headers.push(["Refresh", `0;url=${redirect.destination}`]);
}
return {
type: "response",
statusCode,
headers,
body: redirect.destination,
};
}
if (isDataReq) {
// TODO(from next.js): change this to a different passing mechanism
const pageData = (renderOpts as any).pageData;
return {
type: "response",
statusCode,
contentType: MIME_APPLICATION_JAVASCRIPT,
headers: [["Content-Type", MIME_APPLICATION_JAVASCRIPT]],
// Page data is only returned if the page had getXxyProps.
body: JSON.stringify(pageData === undefined ? {} : pageData),
};
@ -235,14 +273,16 @@ export default function startHandler({
}
const body = renderResult.toUnchunkedString();
// TODO: handle these
// TODO: handle revalidate
// const sprRevalidate = (renderOpts as any).revalidate;
// const isRedirect = (renderOpts as any).isRedirect;
return {
type: "response",
statusCode,
contentType: renderResult.contentType() ?? MIME_TEXT_HTML_UTF8,
headers: [
["Content-Type", renderResult.contentType() ?? MIME_TEXT_HTML_UTF8],
],
body,
};
}

View file

@ -5,7 +5,8 @@ use turbo_tasks::primitives::StringsVc;
use turbo_tasks_fs::File;
use turbopack_core::asset::AssetContentVc;
use turbopack_dev_server::source::{
ContentSource, ContentSourceContent, ContentSourceData, ContentSourceResultVc, ContentSourceVc,
ContentSource, ContentSourceContentVc, ContentSourceData, ContentSourceResultVc,
ContentSourceVc,
};
use turbopack_node::render::{
node_api_source::NodeApiContentSourceVc, rendered_source::NodeRenderContentSourceVc,
@ -77,9 +78,7 @@ impl ContentSource for DevManifestContentSource {
let file = File::from(manifest_content).with_content_type(APPLICATION_JSON);
Ok(ContentSourceResultVc::exact(
ContentSourceContent::Static(AssetContentVc::from(file).into())
.cell()
.into(),
ContentSourceContentVc::static_content(AssetContentVc::from(file).into()).into(),
))
}
}

View file

@ -10,7 +10,7 @@ use turbo_tasks_memory::{
};
use turbopack_core::asset::AssetContentVc;
use turbopack_dev_server::source::{
ContentSource, ContentSourceContent, ContentSourceData, ContentSourceDataFilter,
ContentSource, ContentSourceContentVc, ContentSourceData, ContentSourceDataFilter,
ContentSourceDataVary, ContentSourceResultVc, ContentSourceVc, NeededData,
};
@ -106,10 +106,9 @@ impl ContentSource for TurboTasksSource {
_ => return Ok(ContentSourceResultVc::not_found()),
};
Ok(ContentSourceResultVc::exact(
ContentSourceContent::Static(
ContentSourceContentVc::static_content(
AssetContentVc::from(File::from(html).with_content_type(TEXT_HTML_UTF_8)).into(),
)
.cell()
.into(),
))
}