Repository: withastro/astro
File: packages/astro/src/core/render/params-and-props.ts (TypeScript)

Code before:
			...AstroErrorData.NoMatchingStaticPathFound,
			message: AstroErrorData.NoMatchingStaticPathFound.message(pathname),
			hint: AstroErrorData.NoMatchingStaticPathFound.hint([route.component]),
		});
	}

	if (mod) {
		validatePrerenderEndpointCollision(route, mod, params);
	}

	const props: Props = matchedStaticPath?.props ? { ...matchedStaticPath.props } : {};

	return props;
}

/**
 * When given a route with the pattern `/[x]/[y]/[z]/svelte`, and a pathname `/a/b/c/svelte`,
 * returns the params object: { x: "a", y: "b", z: "c" }.
 */
export function getParams(route: RouteData, pathname: string): Params {
	if (!route.params.length) return {};
	// The RegExp pattern expects a decoded string, but the pathname is encoded
	// when the URL contains non-English characters.
	const paramsMatch =
		route.pattern.exec(pathname) ||
		route.fallbackRoutes.map((fallbackRoute) => fallbackRoute.pattern.exec(pathname))[0];

	if (!paramsMatch) return {};
	const params: Params = {};
	route.params.forEach((key, i) => {
		if (key.startsWith('...')) {
			params[key.slice(3)] = paramsMatch[i + 1] ? paramsMatch[i + 1] : undefined;
		} else {
			params[key] = paramsMatch[i + 1];
		}
	});
	return params;
}

/**
 * If we have an endpoint at `src/pages/api/[slug].ts` that's prerendered, and the `slug`
 * is `undefined`, throw an error as we can't generate the `/api` file and `/api` directory
 * at the same time. Using something like `[slug].json.ts` instead will work.
 */
function validatePrerenderEndpointCollision(
	route: RouteData,
	mod: ComponentInstance,
	params: Params,
) {
	if (route.type === 'endpoint' && mod.getStaticPaths) {
		const lastSegment = route.segments[route.segments.length - 1];

Review comment (suggestion):
This doesn't seem correct to me. We're looping over all fallback routes and use `exec`, but we always pick the first one. Instead, we should use a for loop, and assign to `paramsMatch` that matches the route.

```js
for (const fallbackRoute in route.fallbackRoutes) {
	if (fallbackRoute.test(pathname)) {
		paramsMatch = fallbackRoute.exec(pathname);
		break;
	}
}
```

Code after:
			...AstroErrorData.NoMatchingStaticPathFound,
			message: AstroErrorData.NoMatchingStaticPathFound.message(pathname),
			hint: AstroErrorData.NoMatchingStaticPathFound.hint([route.component]),
		});
	}

	if (mod) {
		validatePrerenderEndpointCollision(route, mod, params);
	}

	const props: Props = matchedStaticPath?.props ? { ...matchedStaticPath.props } : {};

	return props;
}

/**
 * When given a route with the pattern `/[x]/[y]/[z]/svelte`, and a pathname `/a/b/c/svelte`,
 * returns the params object: { x: "a", y: "b", z: "c" }.
 */
export function getParams(route: RouteData, pathname: string): Params {
	if (!route.params.length) return {};
	// The RegExp pattern expects a decoded string, but the pathname is encoded
	// when the URL contains non-English characters.
	const paramsMatch =
		route.pattern.exec(pathname) ||
		route.fallbackRoutes
			.map((fallbackRoute) => fallbackRoute.pattern.exec(pathname))
			.find((x) => x);
	if (!paramsMatch) return {};
	const params: Params = {};
	route.params.forEach((key, i) => {
		if (key.startsWith('...')) {
			params[key.slice(3)] = paramsMatch[i + 1] ? paramsMatch[i + 1] : undefined;
		} else {
			params[key] = paramsMatch[i + 1];
		}
	});
	return params;
}

/**
 * If we have an endpoint at `src/pages/api/[slug].ts` that's prerendered, and the `slug`
 * is `undefined`, throw an error as we can't generate the `/api` file and `/api` directory
 * at the same time. Using something like `[slug].json.ts` instead will work.
 */
function validatePrerenderEndpointCollision(
	route: RouteData,
	mod: ComponentInstance,
	params: Params,
) {
	if (route.type === 'endpoint' && mod.getStaticPaths) {