Fix Persian user-product URL redirect loop.
Compare decoded/NFC slugs and stop percent-encoding path segments so detail pages no longer 307 themselves into a white screen. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
911aa79530
commit
7bd5f55b92
@@ -13,6 +13,7 @@ import {
|
||||
getUserProductByIdOrNull,
|
||||
getUserProductTechnicalInfoById,
|
||||
listUserProducts,
|
||||
normalizePathSlug,
|
||||
productCategory,
|
||||
productTitle,
|
||||
userProductHref,
|
||||
@@ -51,7 +52,7 @@ export default async function UserProductDetailPage({ params }: PageProps) {
|
||||
if (!product) notFound();
|
||||
|
||||
const canonicalSlug = userProductPathSlug(product);
|
||||
if (slug !== canonicalSlug) {
|
||||
if (normalizePathSlug(slug) !== canonicalSlug) {
|
||||
redirect(userProductHref(product));
|
||||
}
|
||||
|
||||
|
||||
@@ -77,22 +77,36 @@ export function slugifyForUrl(value: string, fallback = "user-product") {
|
||||
return slug || fallback;
|
||||
}
|
||||
|
||||
/** Decode + NFC so route params and API pathSlug compare safely. */
|
||||
export function normalizePathSlug(value: string) {
|
||||
let decoded = value.trim();
|
||||
try {
|
||||
decoded = decodeURIComponent(decoded);
|
||||
} catch {
|
||||
/* already decoded or malformed — keep as-is */
|
||||
}
|
||||
return decoded.normalize("NFC").trim();
|
||||
}
|
||||
|
||||
export function userProductPathSlug(
|
||||
product: Pick<UserProductListItem, "pathSlug" | "titleFa" | "titleEn">,
|
||||
) {
|
||||
const fromApi = product.pathSlug?.trim();
|
||||
if (fromApi) return fromApi;
|
||||
if (fromApi) return normalizePathSlug(fromApi);
|
||||
return slugifyForUrl(
|
||||
product.titleFa?.trim() || product.titleEn?.trim() || "",
|
||||
"user-product",
|
||||
);
|
||||
}
|
||||
|
||||
/** Canonical storefront path: `/user-products/{id}/{pathSlug}`. */
|
||||
/**
|
||||
* Canonical storefront path: `/user-products/{id}/{pathSlug}`.
|
||||
* Leave Unicode unencoded — encoding + Next param decoding caused redirect loops.
|
||||
*/
|
||||
export function userProductHref(
|
||||
product: Pick<UserProductListItem, "id" | "pathSlug" | "titleFa" | "titleEn">,
|
||||
) {
|
||||
return `/user-products/${encodeURIComponent(product.id)}/${encodeURIComponent(userProductPathSlug(product))}`;
|
||||
return `/user-products/${product.id}/${userProductPathSlug(product)}`;
|
||||
}
|
||||
|
||||
export async function listUserProducts(params: ListUserProductsParams = {}) {
|
||||
|
||||
Reference in New Issue
Block a user