diff --git a/.changeset/dark-heads-greet.md b/.changeset/dark-heads-greet.md new file mode 100644 index 000000000000..de769b6e8c7e --- /dev/null +++ b/.changeset/dark-heads-greet.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +fix: match URL-encoded newlines in rest route params diff --git a/packages/adapter-vercel/test/utils.spec.js b/packages/adapter-vercel/test/utils.spec.js index 866523a99351..34286d7c2ff1 100644 --- a/packages/adapter-vercel/test/utils.spec.js +++ b/packages/adapter-vercel/test/utils.spec.js @@ -124,9 +124,9 @@ test('pattern_to_src for route with optional parameter in the middle', () => { }); test('pattern_to_src for route with rest parameter', () => { - run_pattern_to_src_test('/foo/[...bar]', '^/foo(/.*)?/?'); + run_pattern_to_src_test('/foo/[...bar]', '^/foo(/[^]*)?/?'); }); test('pattern_to_src for route with rest parameter in the middle', () => { - run_pattern_to_src_test('/foo/[...bar]/baz', '^/foo(/.*)?/baz/?'); + run_pattern_to_src_test('/foo/[...bar]/baz', '^/foo(/[^]*)?/baz/?'); }); diff --git a/packages/kit/src/core/sync/create_manifest_data/index.spec.js b/packages/kit/src/core/sync/create_manifest_data/index.spec.js index 2642e0c3cce0..c681184446a6 100644 --- a/packages/kit/src/core/sync/create_manifest_data/index.spec.js +++ b/packages/kit/src/core/sync/create_manifest_data/index.spec.js @@ -268,7 +268,7 @@ test('sorts routes with rest correctly', () => { }, { id: '/a/[...rest]', - pattern: '/^/a(?:/(.*))?/?$/', + pattern: '/^/a(?:/([^]*))?/?$/', page: { layouts: [0], errors: [1], leaf: 2 } }, { @@ -277,7 +277,7 @@ test('sorts routes with rest correctly', () => { }, { id: '/b/[...rest]', - pattern: '/^/b(?:/(.*))?/?$/', + pattern: '/^/b(?:/([^]*))?/?$/', page: { layouts: [0], errors: [1], leaf: 3 } } ]); @@ -301,12 +301,12 @@ test('allows rest parameters inside segments', () => { }, { id: '/prefix-[...rest]', - pattern: '/^/prefix-(.*?)/?$/', + pattern: '/^/prefix-([^]*?)/?$/', page: { layouts: [0], errors: [1], leaf: 2 } }, { id: '/[...rest].json', - pattern: '/^/(.*?).json/?$/', + pattern: '/^/([^]*?).json/?$/', endpoint: { file: 'samples/rest-prefix-suffix/[...rest].json/+server.js' } @@ -714,7 +714,7 @@ test('handles pages without .svelte file', () => { }, { id: '/error/[...path]', - pattern: '/^/error(?:/(.*))?/?$/', + pattern: '/^/error(?:/([^]*))?/?$/', page: { layouts: [0, undefined], errors: [1, 2], leaf: 6 } }, { diff --git a/packages/kit/src/utils/routing.js b/packages/kit/src/utils/routing.js index 15f3582bc136..ee129976b6e4 100644 --- a/packages/kit/src/utils/routing.js +++ b/packages/kit/src/utils/routing.js @@ -26,7 +26,7 @@ export function parse_route_id(id) { rest: true, chained: true }); - return '(?:/(.*))?'; + return '(?:/([^]*))?'; } // special case — /[[optional]]/ could contain zero segments const optional_match = /^\[\[(\w+)(?:=(\w+))?\]\]$/.exec(segment); @@ -86,7 +86,7 @@ export function parse_route_id(id) { rest: !!is_rest, chained: is_rest ? i === 1 && parts[0] === '' : false }); - return is_rest ? '(.*?)' : is_optional ? '([^/]*)?' : '([^/]+?)'; + return is_rest ? '([^]*?)' : is_optional ? '([^/]*)?' : '([^/]+?)'; } return escape(content); diff --git a/packages/kit/src/utils/routing.spec.js b/packages/kit/src/utils/routing.spec.js index de7fef129daa..03ab03af3c78 100644 --- a/packages/kit/src/utils/routing.spec.js +++ b/packages/kit/src/utils/routing.spec.js @@ -36,11 +36,11 @@ describe('parse_route_id', () => { params: [{ name: 'slug', matcher: undefined, optional: true, rest: false, chained: false }] }, '/[...catchall]': { - pattern: /^(?:\/(.*))?\/?$/, + pattern: /^(?:\/([^]*))?\/?$/, params: [{ name: 'catchall', matcher: undefined, optional: false, rest: true, chained: true }] }, '/foo/[...catchall]/bar': { - pattern: /^\/foo(?:\/(.*))?\/bar\/?$/, + pattern: /^\/foo(?:\/([^]*))?\/bar\/?$/, params: [{ name: 'catchall', matcher: undefined, optional: false, rest: true, chained: true }] }, '/matched/[id=uuid]': { @@ -244,6 +244,16 @@ describe('exec', () => { route: '/[[slug1=doesntmatch]]/[...slug2=doesntmatch]', path: '/a/b/c', expected: undefined + }, + { + route: '/[...catchall]', + path: '/\n', + expected: { catchall: '\n' } + }, + { + route: '/[[...catchall]]', + path: '/\n', + expected: { catchall: '\n' } } ];