@sitecore-content-sdk/nextjs 2.2.0 → 2.2.1-canary.20260701073911
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -127,11 +127,14 @@ class RedirectsProxy extends proxy_1.ProxyBase {
|
|
|
127
127
|
// Apply regex replacements to the target URL if the pattern is a regex
|
|
128
128
|
const sourcePath = existsRedirect.matchedPath || reqUrl.pathname;
|
|
129
129
|
const pathForCaptureMatch = sourcePath.replace(/\/*$/gi, '') || '/';
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
130
|
+
if ((0, tools_1.isRegexOrUrl)(existsRedirect.pattern) === 'regex') {
|
|
131
|
+
const redirectRegex = this.safeCompileRedirectPattern(existsRedirect.pattern);
|
|
132
|
+
const matched = redirectRegex ? pathForCaptureMatch.match(redirectRegex) : null;
|
|
133
|
+
if (matched) {
|
|
134
|
+
existsRedirect.target = existsRedirect.target.replace(/\$(\d+)/g, (_, index) => {
|
|
135
|
+
return matched[parseInt(index, 10)] || '';
|
|
136
|
+
});
|
|
137
|
+
}
|
|
135
138
|
}
|
|
136
139
|
const isAbsoluteUrl = REGEXP_ABSOLUTE_URL.test(existsRedirect.target);
|
|
137
140
|
const redirectedResponse = isAbsoluteUrl
|
|
@@ -266,7 +269,7 @@ class RedirectsProxy extends proxy_1.ProxyBase {
|
|
|
266
269
|
const patternParts = patternPath.split('/');
|
|
267
270
|
const maybeLocale = patternParts[1].toLowerCase();
|
|
268
271
|
// case insensitive lookup of locales
|
|
269
|
-
if (new RegExp(this.locales.join('|'), 'i').test(maybeLocale)) {
|
|
272
|
+
if (new RegExp(this.locales.map(tools_1.escapeRegExp).join('|'), 'i').test(maybeLocale)) {
|
|
270
273
|
patternPath = patternPath.replace(`/${patternParts[1]}`, `/${maybeLocale}`);
|
|
271
274
|
}
|
|
272
275
|
return ((patternPath === localePath || patternPath === normalizedPath) &&
|
|
@@ -274,7 +277,10 @@ class RedirectsProxy extends proxy_1.ProxyBase {
|
|
|
274
277
|
(0, tools_1.areURLSearchParamsEqual)(new URLSearchParams(patternQS), new URLSearchParams(incomingQS))));
|
|
275
278
|
}
|
|
276
279
|
// process regex rules
|
|
277
|
-
const regex = this.
|
|
280
|
+
const regex = this.safeCompileRedirectPattern(redirect.pattern);
|
|
281
|
+
if (!regex) {
|
|
282
|
+
return false;
|
|
283
|
+
}
|
|
278
284
|
const testRegex = (value) => {
|
|
279
285
|
regex.lastIndex = 0;
|
|
280
286
|
return regex.test(value);
|
|
@@ -309,7 +315,7 @@ class RedirectsProxy extends proxy_1.ProxyBase {
|
|
|
309
315
|
* @private
|
|
310
316
|
*/
|
|
311
317
|
matchRedirectItemRedirect(redirects, locale, currentPath) {
|
|
312
|
-
const nonLocalePath = currentPath.replace(new RegExp(
|
|
318
|
+
const nonLocalePath = currentPath.replace(new RegExp(`^/?${(0, tools_1.escapeRegExp)(locale)}/`, 'i'), '/');
|
|
313
319
|
return redirects.length
|
|
314
320
|
? redirects.find((redirect) => {
|
|
315
321
|
const patternPath = redirect.pattern.replace(/\/*$/g, '').toLowerCase();
|
|
@@ -441,6 +447,23 @@ class RedirectsProxy extends proxy_1.ProxyBase {
|
|
|
441
447
|
}
|
|
442
448
|
return redirect;
|
|
443
449
|
}
|
|
450
|
+
/**
|
|
451
|
+
* Compiles a redirect pattern to RegExp; returns null if Sitecore produced a malformed rule
|
|
452
|
+
* so one bad entry does not fail the entire redirect chain.
|
|
453
|
+
* @param {string} pattern redirect pattern from redirect map
|
|
454
|
+
* @returns {RegExp | null} normalized regex instance, or null when invalid
|
|
455
|
+
* @private
|
|
456
|
+
*/
|
|
457
|
+
safeCompileRedirectPattern(pattern) {
|
|
458
|
+
try {
|
|
459
|
+
return this.getRedirectPatternRegex(pattern);
|
|
460
|
+
}
|
|
461
|
+
catch (error) {
|
|
462
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
463
|
+
console.warn(`[RedirectsProxy] Invalid redirect regex; skipping rule. pattern=${pattern} (${message})`);
|
|
464
|
+
return null;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
444
467
|
/**
|
|
445
468
|
* Converts a redirect pattern string into a RegExp.
|
|
446
469
|
* Supports both JS literal form (`/pattern/i`) and plain regex source (`^/path$`).
|
|
@@ -469,7 +492,7 @@ class RedirectsProxy extends proxy_1.ProxyBase {
|
|
|
469
492
|
if (!urlLocale) {
|
|
470
493
|
return path;
|
|
471
494
|
}
|
|
472
|
-
const localePrefixRegex = new RegExp(`^/${urlLocale}(?=/|$)`, 'i');
|
|
495
|
+
const localePrefixRegex = new RegExp(`^/${(0, tools_1.escapeRegExp)(urlLocale)}(?=/|$)`, 'i');
|
|
473
496
|
const strippedPath = path.replace(localePrefixRegex, '') || '/';
|
|
474
497
|
return strippedPath.startsWith('/') ? strippedPath : `/${strippedPath}`;
|
|
475
498
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { RedirectsService, REDIRECT_TYPE_301, REDIRECT_TYPE_302, REDIRECT_TYPE_SERVER_TRANSFER, } from '@sitecore-content-sdk/content/site';
|
|
2
|
-
import { areURLSearchParamsEqual, escapeNonSpecialQuestionMarks, isRegexOrUrl, mergeURLSearchParams, } from '@sitecore-content-sdk/core/tools';
|
|
2
|
+
import { areURLSearchParamsEqual, escapeNonSpecialQuestionMarks, escapeRegExp, isRegexOrUrl, mergeURLSearchParams, } from '@sitecore-content-sdk/core/tools';
|
|
3
3
|
import { NextResponse } from 'next/server';
|
|
4
4
|
import { ProxyBase, REWRITE_HEADER_NAME } from './proxy';
|
|
5
5
|
import debug from '../debug';
|
|
@@ -121,11 +121,14 @@ export class RedirectsProxy extends ProxyBase {
|
|
|
121
121
|
// Apply regex replacements to the target URL if the pattern is a regex
|
|
122
122
|
const sourcePath = existsRedirect.matchedPath || reqUrl.pathname;
|
|
123
123
|
const pathForCaptureMatch = sourcePath.replace(/\/*$/gi, '') || '/';
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
124
|
+
if (isRegexOrUrl(existsRedirect.pattern) === 'regex') {
|
|
125
|
+
const redirectRegex = this.safeCompileRedirectPattern(existsRedirect.pattern);
|
|
126
|
+
const matched = redirectRegex ? pathForCaptureMatch.match(redirectRegex) : null;
|
|
127
|
+
if (matched) {
|
|
128
|
+
existsRedirect.target = existsRedirect.target.replace(/\$(\d+)/g, (_, index) => {
|
|
129
|
+
return matched[parseInt(index, 10)] || '';
|
|
130
|
+
});
|
|
131
|
+
}
|
|
129
132
|
}
|
|
130
133
|
const isAbsoluteUrl = REGEXP_ABSOLUTE_URL.test(existsRedirect.target);
|
|
131
134
|
const redirectedResponse = isAbsoluteUrl
|
|
@@ -260,7 +263,7 @@ export class RedirectsProxy extends ProxyBase {
|
|
|
260
263
|
const patternParts = patternPath.split('/');
|
|
261
264
|
const maybeLocale = patternParts[1].toLowerCase();
|
|
262
265
|
// case insensitive lookup of locales
|
|
263
|
-
if (new RegExp(this.locales.join('|'), 'i').test(maybeLocale)) {
|
|
266
|
+
if (new RegExp(this.locales.map(escapeRegExp).join('|'), 'i').test(maybeLocale)) {
|
|
264
267
|
patternPath = patternPath.replace(`/${patternParts[1]}`, `/${maybeLocale}`);
|
|
265
268
|
}
|
|
266
269
|
return ((patternPath === localePath || patternPath === normalizedPath) &&
|
|
@@ -268,7 +271,10 @@ export class RedirectsProxy extends ProxyBase {
|
|
|
268
271
|
areURLSearchParamsEqual(new URLSearchParams(patternQS), new URLSearchParams(incomingQS))));
|
|
269
272
|
}
|
|
270
273
|
// process regex rules
|
|
271
|
-
const regex = this.
|
|
274
|
+
const regex = this.safeCompileRedirectPattern(redirect.pattern);
|
|
275
|
+
if (!regex) {
|
|
276
|
+
return false;
|
|
277
|
+
}
|
|
272
278
|
const testRegex = (value) => {
|
|
273
279
|
regex.lastIndex = 0;
|
|
274
280
|
return regex.test(value);
|
|
@@ -303,7 +309,7 @@ export class RedirectsProxy extends ProxyBase {
|
|
|
303
309
|
* @private
|
|
304
310
|
*/
|
|
305
311
|
matchRedirectItemRedirect(redirects, locale, currentPath) {
|
|
306
|
-
const nonLocalePath = currentPath.replace(new RegExp(
|
|
312
|
+
const nonLocalePath = currentPath.replace(new RegExp(`^/?${escapeRegExp(locale)}/`, 'i'), '/');
|
|
307
313
|
return redirects.length
|
|
308
314
|
? redirects.find((redirect) => {
|
|
309
315
|
const patternPath = redirect.pattern.replace(/\/*$/g, '').toLowerCase();
|
|
@@ -435,6 +441,23 @@ export class RedirectsProxy extends ProxyBase {
|
|
|
435
441
|
}
|
|
436
442
|
return redirect;
|
|
437
443
|
}
|
|
444
|
+
/**
|
|
445
|
+
* Compiles a redirect pattern to RegExp; returns null if Sitecore produced a malformed rule
|
|
446
|
+
* so one bad entry does not fail the entire redirect chain.
|
|
447
|
+
* @param {string} pattern redirect pattern from redirect map
|
|
448
|
+
* @returns {RegExp | null} normalized regex instance, or null when invalid
|
|
449
|
+
* @private
|
|
450
|
+
*/
|
|
451
|
+
safeCompileRedirectPattern(pattern) {
|
|
452
|
+
try {
|
|
453
|
+
return this.getRedirectPatternRegex(pattern);
|
|
454
|
+
}
|
|
455
|
+
catch (error) {
|
|
456
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
457
|
+
console.warn(`[RedirectsProxy] Invalid redirect regex; skipping rule. pattern=${pattern} (${message})`);
|
|
458
|
+
return null;
|
|
459
|
+
}
|
|
460
|
+
}
|
|
438
461
|
/**
|
|
439
462
|
* Converts a redirect pattern string into a RegExp.
|
|
440
463
|
* Supports both JS literal form (`/pattern/i`) and plain regex source (`^/path$`).
|
|
@@ -463,7 +486,7 @@ export class RedirectsProxy extends ProxyBase {
|
|
|
463
486
|
if (!urlLocale) {
|
|
464
487
|
return path;
|
|
465
488
|
}
|
|
466
|
-
const localePrefixRegex = new RegExp(`^/${urlLocale}(?=/|$)`, 'i');
|
|
489
|
+
const localePrefixRegex = new RegExp(`^/${escapeRegExp(urlLocale)}(?=/|$)`, 'i');
|
|
467
490
|
const strippedPath = path.replace(localePrefixRegex, '') || '/';
|
|
468
491
|
return strippedPath.startsWith('/') ? strippedPath : `/${strippedPath}`;
|
|
469
492
|
}
|
package/package.json
CHANGED
|
@@ -101,6 +101,14 @@ export declare class RedirectsProxy extends ProxyBase {
|
|
|
101
101
|
* @returns {NextResponse<unknown>} The redirect response.
|
|
102
102
|
*/
|
|
103
103
|
protected createRedirectResponse(url: NextURL | string, res: Response | undefined, status: number, statusText: string): NextResponse;
|
|
104
|
+
/**
|
|
105
|
+
* Compiles a redirect pattern to RegExp; returns null if Sitecore produced a malformed rule
|
|
106
|
+
* so one bad entry does not fail the entire redirect chain.
|
|
107
|
+
* @param {string} pattern redirect pattern from redirect map
|
|
108
|
+
* @returns {RegExp | null} normalized regex instance, or null when invalid
|
|
109
|
+
* @private
|
|
110
|
+
*/
|
|
111
|
+
private safeCompileRedirectPattern;
|
|
104
112
|
/**
|
|
105
113
|
* Converts a redirect pattern string into a RegExp.
|
|
106
114
|
* Supports both JS literal form (`/pattern/i`) and plain regex source (`^/path$`).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redirects-proxy.d.ts","sourceRoot":"","sources":["../../src/proxy/redirects-proxy.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EAItB,YAAY,EAEb,MAAM,oCAAoC,CAAC;
|
|
1
|
+
{"version":3,"file":"redirects-proxy.d.ts","sourceRoot":"","sources":["../../src/proxy/redirects-proxy.ts"],"names":[],"mappings":"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"}
|