File tree 18 files changed +167
-3
lines changed
fixtures/middleware-static-asset-matcher
link-to-redirect-to-cached-page
link-to-rewrite-to-cached-page
18 files changed +167
-3
lines changed Original file line number Diff line number Diff line change @@ -424,14 +424,24 @@ export interface MiddlewareMatcher {
424
424
missing ?: RouteHas [ ]
425
425
}
426
426
427
+ const decodeMaybeEncodedPath = ( path : string ) : string => {
428
+ try {
429
+ return decodeURIComponent ( path )
430
+ } catch {
431
+ return path
432
+ }
433
+ }
434
+
427
435
export function getMiddlewareRouteMatcher ( matchers : MiddlewareMatcher [ ] ) : MiddlewareRouteMatch {
428
436
return (
429
- pathname : string | null | undefined ,
437
+ unsafePathname : string | null | undefined ,
430
438
req : Pick < Request , 'headers' | 'url' > ,
431
439
query : Params ,
432
440
) => {
441
+ const pathname = decodeMaybeEncodedPath ( unsafePathname ?? '' )
442
+
433
443
for ( const matcher of matchers ) {
434
- const routeMatch = new RegExp ( matcher . regexp ) . exec ( pathname ! )
444
+ const routeMatch = new RegExp ( matcher . regexp ) . exec ( pathname )
435
445
if ( ! routeMatch ) {
436
446
continue
437
447
}
Original file line number Diff line number Diff line change @@ -233,6 +233,15 @@ test("requests with x-middleware-subrequest don't skip middleware (GHSA-f82v-jwr
233
233
expect ( response . headers . get ( 'x-test-used-next-version' ) ) . toBe ( '15.2.2' )
234
234
} )
235
235
236
+ test ( 'requests with different encoding than matcher match anyway' , async ( {
237
+ middlewareStaticAssetMatcher,
238
+ } ) => {
239
+ const response = await fetch ( `${ middlewareStaticAssetMatcher . url } /hello%2Fworld.txt` )
240
+
241
+ // middleware was not skipped
242
+ expect ( await response . text ( ) ) . toBe ( 'hello from middleware' )
243
+ } )
244
+
236
245
test . describe ( 'RSC cache poisoning' , ( ) => {
237
246
test ( 'Middleware rewrite' , async ( { page, middleware } ) => {
238
247
const prefetchResponsePromise = new Promise < Response > ( ( resolve ) => {
Original file line number Diff line number Diff line change
1
+ export default function CachingRedirect ( ) {
2
+ return (
3
+ < main >
4
+ < h1 > Hello redirect target</ h1 >
5
+ </ main >
6
+ )
7
+ }
8
+
9
+ export const dynamic = 'force-static'
Original file line number Diff line number Diff line change
1
+ export default function CachingRewrite ( ) {
2
+ return (
3
+ < main >
4
+ < h1 > Hello rewrite target</ h1 >
5
+ </ main >
6
+ )
7
+ }
8
+
9
+ export const dynamic = 'force-static'
Original file line number Diff line number Diff line change
1
+ export const metadata = {
2
+ title : 'Simple Next App' ,
3
+ description : 'Description for Simple Next App' ,
4
+ }
5
+
6
+ export default function RootLayout ( { children } ) {
7
+ return (
8
+ < html lang = "en" >
9
+ < body > { children } </ body >
10
+ </ html >
11
+ )
12
+ }
Original file line number Diff line number Diff line change
1
+ import Link from 'next/link'
2
+
3
+ export default function LinksToRedirectedCachedPage ( ) {
4
+ return (
5
+ < nav >
6
+ < ul >
7
+ < li >
8
+ < Link href = "/test/redirect-to-cached-page" > NextResponse.redirect</ Link >
9
+ </ li >
10
+ </ ul >
11
+ </ nav >
12
+ )
13
+ }
Original file line number Diff line number Diff line change
1
+ import Link from 'next/link'
2
+
3
+ export default function LinksToRewrittenCachedPage ( ) {
4
+ return (
5
+ < nav >
6
+ < ul >
7
+ < li >
8
+ < Link href = "/test/rewrite-to-cached-page" > NextResponse.rewrite</ Link >
9
+ </ li >
10
+ </ ul >
11
+ </ nav >
12
+ )
13
+ }
Original file line number Diff line number Diff line change
1
+ export default function Page ( ) {
2
+ return (
3
+ < main >
4
+ < h1 > Other</ h1 >
5
+ </ main >
6
+ )
7
+ }
Original file line number Diff line number Diff line change
1
+ export default function Home ( ) {
2
+ return (
3
+ < main >
4
+ < h1 > Home</ h1 >
5
+ </ main >
6
+ )
7
+ }
Original file line number Diff line number Diff line change
1
+ import { headers } from 'next/headers'
2
+
3
+ export default function Page ( ) {
4
+ const headersList = headers ( )
5
+ const message = headersList . get ( 'x-hello-from-middleware-req' )
6
+
7
+ return (
8
+ < main >
9
+ < h1 > Message from middleware: { message } </ h1 >
10
+ </ main >
11
+ )
12
+ }
Original file line number Diff line number Diff line change
1
+ export default function Redirect ( ) {
2
+ return (
3
+ < main >
4
+ < h1 > If middleware works, we shoudn't get here</ h1 >
5
+ </ main >
6
+ )
7
+ }
Original file line number Diff line number Diff line change
1
+ export default function Rewrite ( ) {
2
+ return (
3
+ < main >
4
+ < h1 > Hello rewrite</ h1 >
5
+ </ main >
6
+ )
7
+ }
Original file line number Diff line number Diff line change
1
+ export default function Rewrite ( ) {
2
+ return (
3
+ < main >
4
+ < h1 > If middleware works, we shoudn't get here</ h1 >
5
+ </ main >
6
+ )
7
+ }
Original file line number Diff line number Diff line change
1
+ export default function middleware ( ) {
2
+ return new Response ( 'hello from middleware' )
3
+ }
4
+
5
+ export const config = {
6
+ matcher : '/hello/world.txt' ,
7
+ }
Original file line number Diff line number Diff line change
1
+ /** @type {import('next').NextConfig } */
2
+ const nextConfig = {
3
+ output : 'standalone' ,
4
+ eslint : {
5
+ ignoreDuringBuilds : true ,
6
+ } ,
7
+ webpack : ( config ) => {
8
+ // this is a trigger to generate multiple `.next/server/middleware-[hash].js` files instead of
9
+ // single `.next/server/middleware.js` file
10
+ config . optimization . splitChunks . maxSize = 100_000
11
+
12
+ return config
13
+ } ,
14
+ }
15
+
16
+ module . exports = nextConfig
Original file line number Diff line number Diff line change
1
+ {
2
+ "name" : " middleware" ,
3
+ "version" : " 0.1.0" ,
4
+ "private" : true ,
5
+ "scripts" : {
6
+ "postinstall" : " next build" ,
7
+ "dev" : " next dev" ,
8
+ "build" : " next build"
9
+ },
10
+ "dependencies" : {
11
+ "@aws-amplify/adapter-nextjs" : " ^1.0.18" ,
12
+ "aws-amplify" : " ^6.0.18" ,
13
+ "next" : " latest" ,
14
+ "react" : " 18.2.0" ,
15
+ "react-dom" : " 18.2.0"
16
+ }
17
+ }
Original file line number Diff line number Diff line change
1
+ hello from a static asset
Original file line number Diff line number Diff line change @@ -333,10 +333,11 @@ export const fixtureFactories = {
333
333
pnpm : ( ) => createE2EFixture ( 'pnpm' , { packageManger : 'pnpm' } ) ,
334
334
bun : ( ) => createE2EFixture ( 'simple' , { packageManger : 'bun' } ) ,
335
335
middleware : ( ) => createE2EFixture ( 'middleware' ) ,
336
- middlewareSubrequestVuln : ( ) => createE2EFixture ( 'middleware-subrequest-vuln' ) ,
337
336
middlewareI18nExcludedPaths : ( ) => createE2EFixture ( 'middleware-i18n-excluded-paths' ) ,
338
337
middlewareOg : ( ) => createE2EFixture ( 'middleware-og' ) ,
339
338
middlewarePages : ( ) => createE2EFixture ( 'middleware-pages' ) ,
339
+ middlewareStaticAssetMatcher : ( ) => createE2EFixture ( 'middleware-static-asset-matcher' ) ,
340
+ middlewareSubrequestVuln : ( ) => createE2EFixture ( 'middleware-subrequest-vuln' ) ,
340
341
pageRouter : ( ) => createE2EFixture ( 'page-router' ) ,
341
342
pageRouterBasePathI18n : ( ) => createE2EFixture ( 'page-router-base-path-i18n' ) ,
342
343
turborepo : ( ) =>
You can’t perform that action at this time.
0 commit comments