1
- import { CacheClient , debug , MemoryCacheClient } from '@sitecore-jss/sitecore-jss' ;
1
+ import { debug } from '@sitecore-jss/sitecore-jss' ;
2
2
import {
3
3
GraphQLRedirectsService ,
4
4
GraphQLRedirectsServiceConfig ,
@@ -16,6 +16,7 @@ import { MiddlewareBase, MiddlewareBaseConfig } from './middleware';
16
16
17
17
const REGEXP_CONTEXT_SITE_LANG = new RegExp ( / \$ s i t e L a n g / , 'i' ) ;
18
18
const REGEXP_ABSOLUTE_URL = new RegExp ( '^(?:[a-z]+:)?//' , 'i' ) ;
19
+ const NAME_NETLIFY = 'netlify' ;
19
20
20
21
type RedirectResult = RedirectInfo & { matchedQueryString ?: string } ;
21
22
@@ -37,7 +38,6 @@ export type RedirectsMiddlewareConfig = Omit<GraphQLRedirectsServiceConfig, 'fet
37
38
export class RedirectsMiddleware extends MiddlewareBase {
38
39
private redirectsService : GraphQLRedirectsService ;
39
40
private locales : string [ ] ;
40
- private cache : CacheClient < RedirectResult | boolean | undefined > ;
41
41
42
42
/**
43
43
* @param {RedirectsMiddlewareConfig } [config] redirects middleware config
@@ -49,10 +49,6 @@ export class RedirectsMiddleware extends MiddlewareBase {
49
49
// (underlying default 'cross-fetch' is not currently compatible: https://github.com/lquixada/cross-fetch/issues/78)
50
50
this . redirectsService = new GraphQLRedirectsService ( { ...config , fetch : fetch } ) ;
51
51
this . locales = config . locales ;
52
- this . cache = new MemoryCacheClient < RedirectResult | boolean | undefined > ( {
53
- cacheEnabled : config . cacheEnabled ,
54
- cacheTimeout : config . cacheTimeout ,
55
- } ) ;
56
52
}
57
53
58
54
/**
@@ -85,15 +81,24 @@ export class RedirectsMiddleware extends MiddlewareBase {
85
81
} ) ;
86
82
87
83
const createResponse = async ( ) => {
84
+ const response = res || NextResponse . next ( ) ;
85
+
88
86
if ( this . config . disabled && this . config . disabled ( req , res || NextResponse . next ( ) ) ) {
89
87
debug . redirects ( 'skipped (redirects middleware is disabled)' ) ;
90
- return res || NextResponse . next ( ) ;
88
+ return response ;
91
89
}
92
90
93
91
if ( this . isPreview ( req ) || this . excludeRoute ( pathname ) ) {
94
92
debug . redirects ( 'skipped (%s)' , this . isPreview ( req ) ? 'preview' : 'route excluded' ) ;
95
93
96
- return res || NextResponse . next ( ) ;
94
+ return response ;
95
+ }
96
+
97
+ // Skip prefetch requests
98
+ if ( this . isPrefetch ( req ) ) {
99
+ debug . redirects ( 'skipped (prefetch)' ) ;
100
+ response . headers . set ( 'x-middleware-cache' , 'no-cache' ) ;
101
+ return response ;
97
102
}
98
103
99
104
site = this . getSite ( req , res ) ;
@@ -104,7 +109,7 @@ export class RedirectsMiddleware extends MiddlewareBase {
104
109
if ( ! existsRedirect ) {
105
110
debug . redirects ( 'skipped (redirect does not exist)' ) ;
106
111
107
- return res || NextResponse . next ( ) ;
112
+ return response ;
108
113
}
109
114
110
115
// Find context site language and replace token
@@ -160,16 +165,16 @@ export class RedirectsMiddleware extends MiddlewareBase {
160
165
/** return Response redirect with http code of redirect type */
161
166
switch ( existsRedirect . redirectType ) {
162
167
case REDIRECT_TYPE_301 : {
163
- return this . createRedirectResponse ( url , res , 301 , 'Moved Permanently' ) ;
168
+ return this . createRedirectResponse ( url , response , 301 , 'Moved Permanently' ) ;
164
169
}
165
170
case REDIRECT_TYPE_302 : {
166
- return this . createRedirectResponse ( url , res , 302 , 'Found' ) ;
171
+ return this . createRedirectResponse ( url , response , 302 , 'Found' ) ;
167
172
}
168
173
case REDIRECT_TYPE_SERVER_TRANSFER : {
169
- return this . rewrite ( url . href , req , res || NextResponse . next ( ) ) ;
174
+ return this . rewrite ( url . href , req , response ) ;
170
175
}
171
176
default :
172
- return res || NextResponse . next ( ) ;
177
+ return response ;
173
178
}
174
179
} ;
175
180
@@ -199,29 +204,14 @@ export class RedirectsMiddleware extends MiddlewareBase {
199
204
const { pathname : targetURL , search : targetQS = '' , locale } = this . normalizeUrl (
200
205
req . nextUrl . clone ( )
201
206
) ;
202
- const cacheKey = `${ targetURL } -${ targetQS } -${ locale } ` ;
203
- const cachedRedirect = this . cache . getCacheValue ( cacheKey ) ;
204
-
205
- if ( cachedRedirect !== null ) {
206
- return typeof cachedRedirect === 'boolean' ? undefined : cachedRedirect ;
207
- }
208
-
207
+ const normalizedPath = targetURL . replace ( / \/ * $ / gi, '' ) ;
209
208
const redirects = await this . redirectsService . fetchRedirects ( siteName ) ;
210
-
211
209
const language = this . getLanguage ( req ) ;
212
210
const modifyRedirects = structuredClone ( redirects ) ;
211
+ let matchedQueryString : string | undefined ;
213
212
214
- const result = modifyRedirects . length
213
+ return modifyRedirects . length
215
214
? modifyRedirects . find ( ( redirect : RedirectResult ) => {
216
- // generate cache key for the current pattern
217
- const chachedPatternResultKey = `${ cacheKey } -${ redirect . pattern } -${ redirect . target } ` ;
218
- // Check if the result is already cached
219
- const chachedPatternResult = this . cache . getCacheValue ( chachedPatternResultKey ) ;
220
-
221
- if ( chachedPatternResult !== null ) {
222
- return chachedPatternResult ;
223
- }
224
-
225
215
// Modify the redirect pattern to ignore the language prefix in the path
226
216
// And escapes non-special "?" characters in a string or regex.
227
217
redirect . pattern = this . escapeNonSpecialQuestionMarks (
@@ -260,34 +250,35 @@ export class RedirectsMiddleware extends MiddlewareBase {
260
250
* it returns `undefined`. The `matchedQueryString` is later used to indicate whether the query
261
251
* string contributed to a successful redirect match.
262
252
*/
263
- const matchedQueryString = this . isPermutedQueryMatch ( {
264
- pathname : targetURL ,
265
- queryString : targetQS ,
266
- pattern : redirect . pattern ,
267
- locale,
268
- } ) ;
253
+ if ( req . headers . get ( 'cdn-loop' ) === NAME_NETLIFY ) {
254
+ matchedQueryString = this . getPermutedQueryMatch ( {
255
+ pathname : normalizedPath ,
256
+ queryString : targetQS ,
257
+ pattern : redirect . pattern ,
258
+ locale,
259
+ } ) ;
260
+ } else {
261
+ matchedQueryString = [
262
+ regexParser ( redirect . pattern ) . test ( `${ normalizedPath } ${ targetQS } ` ) ,
263
+ regexParser ( redirect . pattern ) . test ( `/${ locale } ${ normalizedPath } ${ targetQS } ` ) ,
264
+ ] . some ( Boolean )
265
+ ? targetQS
266
+ : undefined ;
267
+ }
269
268
270
269
// Save the matched query string (if found) into the redirect object
271
270
redirect . matchedQueryString = matchedQueryString || '' ;
272
271
273
- const matchedPatterResult =
272
+ // Return the redirect if the URL path or any query string permutation matches the pattern
273
+ return (
274
274
! ! (
275
275
regexParser ( redirect . pattern ) . test ( targetURL ) ||
276
276
regexParser ( redirect . pattern ) . test ( `/${ req . nextUrl . locale } ${ targetURL } ` ) ||
277
277
matchedQueryString
278
- ) && ( redirect . locale ? redirect . locale . toLowerCase ( ) === locale . toLowerCase ( ) : true ) ;
279
-
280
- // Save cache the result for the current pattern
281
- this . cache . setCacheValue ( chachedPatternResultKey , matchedPatterResult ) ;
282
-
283
- // Return the redirect if the URL path or any query string permutation matches the pattern
284
- return matchedPatterResult ;
278
+ ) && ( redirect . locale ? redirect . locale . toLowerCase ( ) === locale . toLowerCase ( ) : true )
279
+ ) ;
285
280
} )
286
281
: undefined ;
287
-
288
- this . cache . setCacheValue ( cacheKey , result ? result : undefined ) ;
289
-
290
- return result ;
291
282
}
292
283
293
284
/**
@@ -372,7 +363,7 @@ export class RedirectsMiddleware extends MiddlewareBase {
372
363
* @param {string } [params.locale] - The locale prefix to include in the URL if present.
373
364
* @returns {string | undefined } - return query string if any of the query permutations match the provided pattern, undefined otherwise.
374
365
*/
375
- private isPermutedQueryMatch ( {
366
+ private getPermutedQueryMatch ( {
376
367
pathname,
377
368
queryString,
378
369
pattern,
@@ -389,11 +380,10 @@ export class RedirectsMiddleware extends MiddlewareBase {
389
380
'?' + permutation . map ( ( [ key , value ] ) => `${ key } =${ value } ` ) . join ( '&' )
390
381
) ;
391
382
392
- const normalizedPath = pathname . replace ( / \/ * $ / gi, '' ) ;
393
383
return listOfPermuted . find ( ( query : string ) =>
394
384
[
395
- regexParser ( pattern ) . test ( `${ normalizedPath } ${ query } ` ) ,
396
- regexParser ( pattern ) . test ( `/${ locale } ${ normalizedPath } ${ query } ` ) ,
385
+ regexParser ( pattern ) . test ( `${ pathname } ${ query } ` ) ,
386
+ regexParser ( pattern ) . test ( `/${ locale } ${ pathname } ${ query } ` ) ,
397
387
] . some ( Boolean )
398
388
) ;
399
389
}
0 commit comments