Bug fix: Order of params for routing has to match (#2593)
* make sure route params are sorted before comparing stringified keys * including changeset for a patch release
This commit is contained in:
parent
b4dcc0f8d3
commit
40c0e2b3f6
4 changed files with 32 additions and 5 deletions
5
.changeset/sweet-spoons-cheer.md
Normal file
5
.changeset/sweet-spoons-cheer.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Dynamic route params should ignore param order when matching paths
|
|
@ -33,8 +33,7 @@ async function getParamsAndProps(opts: GetParamsAndPropsOptions): Promise<[Param
|
|||
routeCacheEntry = await callGetStaticPaths(mod, route, true, logging);
|
||||
routeCache.set(route, routeCacheEntry);
|
||||
}
|
||||
const paramsKey = JSON.stringify(params);
|
||||
const matchedStaticPath = findPathItemByKey(routeCacheEntry.staticPaths, paramsKey);
|
||||
const matchedStaticPath = findPathItemByKey(routeCacheEntry.staticPaths, params);
|
||||
if (!matchedStaticPath) {
|
||||
throw new Error(`[getStaticPaths] route pattern matched, but no matching static path found. (${pathname})`);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import type { ComponentInstance, GetStaticPathsItem, GetStaticPathsResult, GetStaticPathsResultKeyed, RouteData, RSS } from '../../@types/astro';
|
||||
import type { ComponentInstance, GetStaticPathsItem, GetStaticPathsResult, GetStaticPathsResultKeyed, Params, RouteData, RSS } from '../../@types/astro';
|
||||
import { LogOptions, warn, debug } from '../logger.js';
|
||||
|
||||
import { generatePaginateFunction } from './paginate.js';
|
||||
|
@ -6,6 +6,11 @@ import { validateGetStaticPathsModule, validateGetStaticPathsResult } from '../r
|
|||
|
||||
type RSSFn = (...args: any[]) => any;
|
||||
|
||||
function stringifyParams(params: Params) {
|
||||
// Always sort keys before stringifying to make sure objects match regardless of parameter ordering
|
||||
return JSON.stringify(params, Object.keys(params).sort());
|
||||
}
|
||||
|
||||
export async function callGetStaticPaths(mod: ComponentInstance, route: RouteData, isValidate: boolean, logging: LogOptions): Promise<RouteCacheEntry> {
|
||||
validateGetStaticPathsModule(mod);
|
||||
const resultInProgress = {
|
||||
|
@ -23,7 +28,7 @@ export async function callGetStaticPaths(mod: ComponentInstance, route: RouteDat
|
|||
const keyedStaticPaths = staticPaths as GetStaticPathsResultKeyed;
|
||||
keyedStaticPaths.keyed = new Map<string, GetStaticPathsItem>();
|
||||
for (const sp of keyedStaticPaths) {
|
||||
const paramsKey = JSON.stringify(sp.params);
|
||||
const paramsKey = stringifyParams(sp.params);
|
||||
keyedStaticPaths.keyed.set(paramsKey, sp);
|
||||
}
|
||||
if (isValidate) {
|
||||
|
@ -73,7 +78,8 @@ export class RouteCache {
|
|||
}
|
||||
}
|
||||
|
||||
export function findPathItemByKey(staticPaths: GetStaticPathsResultKeyed, paramsKey: string) {
|
||||
export function findPathItemByKey(staticPaths: GetStaticPathsResultKeyed, params: Params) {
|
||||
const paramsKey = stringifyParams(params);
|
||||
let matchedStaticPath = staticPaths.keyed.get(paramsKey);
|
||||
if (matchedStaticPath) {
|
||||
return matchedStaticPath;
|
||||
|
|
17
packages/astro/test/fixtures/astro-get-static-paths/src/pages/blog/[year]/[slug].astro
vendored
Normal file
17
packages/astro/test/fixtures/astro-get-static-paths/src/pages/blog/[year]/[slug].astro
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
---
|
||||
export async function getStaticPaths() {
|
||||
return [
|
||||
{ params: { year: '2022', slug: 'post-1' } },
|
||||
{ params: { slug: 'post-2', year: '2022' } },
|
||||
]
|
||||
}
|
||||
|
||||
const { year, slug } = Astro.request.params
|
||||
---
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>{year} | {slug}</title>
|
||||
</head>
|
||||
<body></body>
|
||||
</html>
|
Loading…
Reference in a new issue