Skip to content

Commit

Permalink
fix: route intercepts causing 404s + missing params (cloudflare#564)
Browse files Browse the repository at this point in the history
  • Loading branch information
james-elicx authored Nov 30, 2023
1 parent 61d0a2f commit 1e73555
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 6 deletions.
5 changes: 5 additions & 0 deletions .changeset/brave-cougars-melt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@cloudflare/next-on-pages': patch
---

Fix route intercepts causing 404s for the non-intercepted route.
5 changes: 5 additions & 0 deletions .changeset/dull-wolves-arrive.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@cloudflare/next-on-pages': patch
---

Fix route intercept modals not getting all the parameters for a route.
3 changes: 2 additions & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
"printWidth": 80,
"singleQuote": true,
"arrowParens": "avoid",
"semi": true
"semi": true,
"trailingComma": "all"
}
25 changes: 23 additions & 2 deletions packages/next-on-pages/templates/_worker.js/routes-matcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,10 @@ export class RoutesMatcher {
*/
private checkRouteMatch(
route: VercelSource,
checkStatus?: boolean,
{
checkStatus,
checkIntercept,
}: { checkStatus: boolean; checkIntercept: boolean },
): { routeMatch: MatchPCREResult; routeDest?: string } | undefined {
const srcMatch = matchPCRE(route.src, this.path, route.caseSensitive);
if (!srcMatch.match) return;
Expand Down Expand Up @@ -136,6 +139,18 @@ export class RoutesMatcher {
return;
}

if (checkIntercept && route.dest) {
const interceptRouteRegex = /\/(\(\.+\))+/;
const destIsIntercept = interceptRouteRegex.test(route.dest);
const pathIsIntercept = interceptRouteRegex.test(this.path);

// If the new destination is an intercept route, only allow it if the current path is also
// an intercept route.
if (destIsIntercept && !pathIsIntercept) {
return;
}
}

return { routeMatch: srcMatch, routeDest: hasFieldProps.routeDest };
}

Expand Down Expand Up @@ -441,7 +456,13 @@ export class RoutesMatcher {
): Promise<CheckRouteStatus> {
const localeFriendlyRoute = this.getLocaleFriendlyRoute(rawRoute, phase);
const { routeMatch, routeDest } =
this.checkRouteMatch(localeFriendlyRoute, phase === 'error') ?? {};
this.checkRouteMatch(localeFriendlyRoute, {
checkStatus: phase === 'error',
// The build output config correctly maps relevant request paths to be intercepts in the
// `none` phase, while the `rewrite` phase can contain entries that rewrite to an intercept
// that matches requests that are not actually intercepts, causing a 404.
checkIntercept: phase === 'rewrite',
}) ?? {};

const route: VercelSource = { ...localeFriendlyRoute, dest: routeDest };

Expand Down
14 changes: 11 additions & 3 deletions packages/next-on-pages/templates/_worker.js/utils/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ export function isUrl(url: string): boolean {
* Next.js fails to derive the correct route parameters and so we need to set them manually.
* https://github.com/vercel/next.js/blob/canary/packages/next/src/lib/constants.ts#L3
*
* For params prefixed with `nxtI`, this is a route intercept. It sets the param without the prefix,
* and removes any intercepts from the param's value. This is so that the route intercept is able
* to have the correct route parameters for the page.
* https://github.com/vercel/next.js/blob/cdf2b79ea/packages/next/src/shared/lib/router/utils/route-regex.ts#L6
*
* @param target Target that search params will be applied to.
* @param source Source search params to apply to the target.
*/
Expand All @@ -60,10 +65,13 @@ export function applySearchParams(
source: URLSearchParams,
) {
for (const [key, value] of source.entries()) {
const paramMatch = /^nxtP(.+)$/.exec(key);
if (paramMatch?.[1]) {
const nxtParamMatch = /^nxtP(.+)$/.exec(key);
const nxtInterceptMatch = /^nxtI(.+)$/.exec(key);
if (nxtParamMatch?.[1]) {
target.set(key, value);
target.set(paramMatch[1], value);
target.set(nxtParamMatch[1], value);
} else if (nxtInterceptMatch?.[1]) {
target.set(nxtInterceptMatch[1], value.replace(/(\(\.+\))+/, ''));
} else if (
!target.has(key) ||
(!!value && !target.getAll(key).includes(value))
Expand Down

0 comments on commit 1e73555

Please sign in to comment.