Skip to content

Commit

Permalink
fix: add afterFiles and fallback
Browse files Browse the repository at this point in the history
  • Loading branch information
conico974 committed Aug 29, 2023
1 parent 023f707 commit 1fc4ec5
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 20 deletions.
7 changes: 7 additions & 0 deletions packages/open-next/src/adapters/next-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ export interface RouteDefinition {
regex: string;
}

export interface DataRouteDefinition {
page: string;
dataRouteRegex: string;
routeKeys?: string;
}

export interface RewriteMatcher {
type: "header" | "cookie" | "query" | "host";
key: string;
Expand All @@ -62,6 +68,7 @@ export interface RedirectDefinition extends RewriteDefinition {
export interface RoutesManifest {
dynamicRoutes: RouteDefinition[];
staticRoutes: RouteDefinition[];
dataRoutes: DataRouteDefinition[];
rewrites: {
beforeFiles: RewriteDefinition[];
afterFiles: RewriteDefinition[];
Expand Down
14 changes: 10 additions & 4 deletions packages/open-next/src/adapters/routing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,11 @@ export function handleRewrites<T extends RewriteDefinition>(
}

return {
rawPath: rewrittenUrl,
url: `${rewrittenUrl}${urlQueryString ? `?${urlQueryString}` : ""}`,
internalEvent: {
...internalEvent,
rawPath: rewrittenUrl,
url: `${rewrittenUrl}${urlQueryString ? `?${urlQueryString}` : ""}`,
},
__rewrite: rewrite,
isExternalRewrite,
};
Expand All @@ -134,12 +137,15 @@ export function handleRedirects(
internalEvent: InternalEvent,
redirects: RedirectDefinition[],
) {
const { url, __rewrite } = handleRewrites(internalEvent, redirects);
const { internalEvent: _internalEvent, __rewrite } = handleRewrites(
internalEvent,
redirects,
);
if (__rewrite && !__rewrite.internal) {
return {
statusCode: __rewrite.statusCode ?? 308,
headers: {
Location: url,
Location: _internalEvent.url,
},
};
}
Expand Down
63 changes: 53 additions & 10 deletions packages/open-next/src/adapters/server-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export async function handler(
}

// Parse Lambda event and create Next.js request
const internalEvent = convertFrom(event);
let internalEvent = convertFrom(event);

// WORKAROUND: Set `x-forwarded-host` header (AWS specific) — https://github.com/serverless-stack/open-next#workaround-set-x-forwarded-host-header-aws-specific
if (internalEvent.headers["x-forwarded-host"]) {
Expand All @@ -109,14 +109,45 @@ export async function handler(
return redirect;
}

const { rawPath, url, isExternalRewrite } = handleRewrites(
let isExternalRewrite = false;
// First rewrite to be applied
const beforeRewrites = handleRewrites(
internalEvent,
routesManifest.rewrites,
routesManifest.rewrites.beforeFiles,
);
internalEvent = beforeRewrites.internalEvent;
isExternalRewrite = beforeRewrites.isExternalRewrite;

const isStaticRoute = routesManifest.routes.static.some((route) =>
new RegExp(route.regex).test(internalEvent.rawPath),
);

if (!isStaticRoute && !isExternalRewrite) {
// Second rewrite to be applied
const afterRewrites = handleRewrites(
internalEvent,
routesManifest.rewrites.afterFiles,
);
internalEvent = afterRewrites.internalEvent;
isExternalRewrite = afterRewrites.isExternalRewrite;
}

const isDynamicRoute = routesManifest.routes.dynamic.some((route) =>
new RegExp(route.regex).test(internalEvent.rawPath),
);
if (!isDynamicRoute && !isStaticRoute && !isExternalRewrite) {
// Fallback rewrite to be applied
const fallbackRewrites = handleRewrites(
internalEvent,
routesManifest.rewrites.fallback,
);
internalEvent = fallbackRewrites.internalEvent;
isExternalRewrite = fallbackRewrites.isExternalRewrite;
}

const reqProps = {
method: internalEvent.method,
url,
url: internalEvent.url,
//WORKAROUND: We pass this header to the serverless function to mimic a prefetch request which will not trigger revalidation since we handle revalidation differently
// There is 3 way we can handle revalidation:
// 1. We could just let the revalidation go as normal, but due to race condtions the revalidation will be unreliable
Expand All @@ -129,7 +160,7 @@ export async function handler(
debug("IncomingMessage constructor props", reqProps);
const req = new IncomingMessage(reqProps);
const res = new ServerResponse({ method: reqProps.method });
setNextjsPrebundledReact(rawPath);
setNextjsPrebundledReact(internalEvent.rawPath);
if (isExternalRewrite) {
await proxyRequest(req, res);
} else {
Expand All @@ -148,10 +179,17 @@ export async function handler(
const body = ServerResponse.body(res).toString(encoding);
debug("ServerResponse data", { statusCode, headers, isBase64Encoded, body });

fixCacheHeaderForHtmlPages(internalEvent.rawPath, headers);
fixSWRCacheHeader(headers);
addOpenNextHeader(headers);
await revalidateIfRequired(internalEvent.headers.host, rawPath, headers, req);
if (!isExternalRewrite) {
fixCacheHeaderForHtmlPages(internalEvent.rawPath, headers);
fixSWRCacheHeader(headers);
addOpenNextHeader(headers);
await revalidateIfRequired(
internalEvent.headers.host,
internalEvent.rawPath,
headers,
req,
);
}

return convertTo({
type: internalEvent.type,
Expand Down Expand Up @@ -180,7 +218,12 @@ function setBuildIdEnv() {
function setNextjsPrebundledReact(rawPath: string) {
// WORKAROUND: Set `__NEXT_PRIVATE_PREBUNDLED_REACT` to use prebundled React — https://github.com/serverless-stack/open-next#workaround-set-__next_private_prebundled_react-to-use-prebundled-react

const route = routesManifest.routes.find((route) =>
const routes = [
...routesManifest.routes.static,
...routesManifest.routes.dynamic,
];

const route = routes.find((route) =>
new RegExp(route.regex).test(rawPath ?? ""),
);

Expand Down
23 changes: 17 additions & 6 deletions packages/open-next/src/adapters/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,24 @@ export function loadRoutesManifest(nextDir: string) {
const json = fs.readFileSync(filePath, "utf-8");
const routesManifest = JSON.parse(json) as RoutesManifest;

// TODO: do we need to include rewrites.afterFiles and rewrites.fallback here?
const rewrites = routesManifest.rewrites.beforeFiles ?? [];
// Rewrite routes first, then static routes then dynamic routes
const _dataRoutes = routesManifest.dataRoutes ?? [];
const dataRoutes = {
static: _dataRoutes.filter((r) => r.routeKeys === undefined),
dynamic: _dataRoutes.filter((r) => r.routeKeys !== undefined),
};

return {
rewrites,
redirects: routesManifest.redirects,
routes: [...routesManifest.staticRoutes, ...routesManifest.dynamicRoutes],
rewrites: {
beforeFiles: routesManifest.rewrites.beforeFiles ?? [],
afterFiles: routesManifest.rewrites.afterFiles ?? [],
fallback: routesManifest.rewrites.fallback ?? [],
},
redirects: routesManifest.redirects ?? [],
routes: {
static: routesManifest.staticRoutes ?? [],
dynamic: routesManifest.dynamicRoutes ?? [],
data: dataRoutes,
},
};
}

Expand Down
4 changes: 4 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 1fc4ec5

Please sign in to comment.