From 4ed9558ed1dbcb1dd0cb7fbc2a60071e3a200314 Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Thu, 2 Sep 2021 21:41:13 -0700 Subject: [PATCH] [fix] don't decode URL when finding matching route --- .changeset/two-tigers-cry.md | 5 +++++ packages/kit/src/core/create_manifest_data/index.js | 11 ++++------- .../kit/src/core/create_manifest_data/index.spec.js | 5 ++++- .../samples/encoding/\345\234\237\350\261\206.svelte" | 0 packages/kit/src/runtime/client/renderer.js | 6 +++--- packages/kit/src/runtime/client/router.js | 5 ++--- packages/kit/src/runtime/client/types.d.ts | 1 - packages/kit/src/runtime/server/index.js | 3 +-- .../kit/test/apps/basics/src/routes/encoded/_tests.js | 10 ++++++++++ 9 files changed, 29 insertions(+), 17 deletions(-) create mode 100644 .changeset/two-tigers-cry.md create mode 100644 "packages/kit/src/core/create_manifest_data/test/samples/encoding/\345\234\237\350\261\206.svelte" diff --git a/.changeset/two-tigers-cry.md b/.changeset/two-tigers-cry.md new file mode 100644 index 000000000000..d6a9a5a4e9f5 --- /dev/null +++ b/.changeset/two-tigers-cry.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +[fix] don't decode URL when finding matching route diff --git a/packages/kit/src/core/create_manifest_data/index.js b/packages/kit/src/core/create_manifest_data/index.js index 8cb6aa87aec0..acef1c8ea6a7 100644 --- a/packages/kit/src/core/create_manifest_data/index.js +++ b/packages/kit/src/core/create_manifest_data/index.js @@ -388,13 +388,10 @@ function get_pattern(segments, add_trailing_slash) { .map((part) => { return part.dynamic ? '([^/]+?)' - : part.content - .normalize() - .replace(/\?/g, '%3F') - .replace(/#/g, '%23') - .replace(/%5B/g, '[') - .replace(/%5D/g, ']') - .replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + : encodeURIComponent(part.content.normalize()).replace( + /[.*+?^${}()|[\]\\]/g, + '\\$&' + ); }) .join(''); }) diff --git a/packages/kit/src/core/create_manifest_data/index.spec.js b/packages/kit/src/core/create_manifest_data/index.spec.js index 2f0a80d0fd9d..203a6421de59 100644 --- a/packages/kit/src/core/create_manifest_data/index.spec.js +++ b/packages/kit/src/core/create_manifest_data/index.spec.js @@ -132,18 +132,20 @@ test('creates routes with layout', () => { ]); }); -test('encodes invalid characters', () => { +test('encoding of characters', () => { const { components, routes } = create('samples/encoding'); // had to remove ? and " because windows // const quote = 'samples/encoding/".svelte'; const hash = 'samples/encoding/#.svelte'; + const potato = 'samples/encoding/土豆.svelte'; // const question_mark = 'samples/encoding/?.svelte'; assert.equal(components, [ layout, error, + potato, // quote, hash // question_mark @@ -152,6 +154,7 @@ test('encodes invalid characters', () => { assert.equal( routes.map((p) => p.pattern), [ + /^\/%E5%9C%9F%E8%B1%86\/?$/, // /^\/%22\/?$/, /^\/%23\/?$/ // /^\/%3F\/?$/ diff --git "a/packages/kit/src/core/create_manifest_data/test/samples/encoding/\345\234\237\350\261\206.svelte" "b/packages/kit/src/core/create_manifest_data/test/samples/encoding/\345\234\237\350\261\206.svelte" new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/packages/kit/src/runtime/client/renderer.js b/packages/kit/src/runtime/client/renderer.js index 4f3de22b7da2..eb5399658cc4 100644 --- a/packages/kit/src/runtime/client/renderer.js +++ b/packages/kit/src/runtime/client/renderer.js @@ -541,8 +541,8 @@ export class Renderer { * @param {boolean} no_cache * @returns {Promise} undefined if fallthrough */ - async _load({ route, info: { path, decoded_path, query } }, no_cache) { - const key = `${decoded_path}?${query}`; + async _load({ route, info: { path, query } }, no_cache) { + const key = `${path}?${query}`; if (!no_cache) { const cached = this.cache.get(key); @@ -552,7 +552,7 @@ export class Renderer { const [pattern, a, b, get_params] = route; const params = get_params ? // the pattern is for the route which we've already matched to this path - get_params(/** @type {RegExpExecArray} */ (pattern.exec(decoded_path))) + get_params(/** @type {RegExpExecArray} */ (pattern.exec(path))) : {}; const changed = this.current.page && { diff --git a/packages/kit/src/runtime/client/router.js b/packages/kit/src/runtime/client/router.js index 9fb9c5dd0715..95fafcca3426 100644 --- a/packages/kit/src/runtime/client/router.js +++ b/packages/kit/src/runtime/client/router.js @@ -170,13 +170,12 @@ export class Router { if (this.owns(url)) { const path = url.pathname.slice(this.base.length) || '/'; - const decoded_path = decodeURI(path); - const routes = this.routes.filter(([pattern]) => pattern.test(decoded_path)); + const routes = this.routes.filter(([pattern]) => pattern.test(path)); const query = new URLSearchParams(url.search); const id = `${path}?${query}`; - return { id, routes, path, decoded_path, query }; + return { id, routes, path, query }; } } diff --git a/packages/kit/src/runtime/client/types.d.ts b/packages/kit/src/runtime/client/types.d.ts index e5865fa3591b..82a91d903424 100644 --- a/packages/kit/src/runtime/client/types.d.ts +++ b/packages/kit/src/runtime/client/types.d.ts @@ -5,7 +5,6 @@ export type NavigationInfo = { id: string; routes: CSRRoute[]; path: string; - decoded_path: string; query: URLSearchParams; }; diff --git a/packages/kit/src/runtime/server/index.js b/packages/kit/src/runtime/server/index.js index 8d6d4be7050f..d915cec6fa27 100644 --- a/packages/kit/src/runtime/server/index.js +++ b/packages/kit/src/runtime/server/index.js @@ -54,9 +54,8 @@ export async function respond(incoming, options, state = {}) { }); } - const decoded = decodeURI(request.path); for (const route of options.manifest.routes) { - const match = route.pattern.exec(decoded); + const match = route.pattern.exec(request.path); if (!match) continue; const response = diff --git a/packages/kit/test/apps/basics/src/routes/encoded/_tests.js b/packages/kit/test/apps/basics/src/routes/encoded/_tests.js index cb33123d204c..be9911e55df0 100644 --- a/packages/kit/test/apps/basics/src/routes/encoded/_tests.js +++ b/packages/kit/test/apps/basics/src/routes/encoded/_tests.js @@ -9,6 +9,16 @@ export default function (test) { assert.equal(decodeURI(await page.innerHTML('h3')), '/encoded/苗条'); }); + test('visits a route with a doubly encoded space', '/encoded/test%2520me', async ({ page }) => { + assert.equal(await page.innerHTML('h2'), '/encoded/test%2520me: test%20me'); + assert.equal(await page.innerHTML('h3'), '/encoded/test%2520me: test%20me'); + }); + + test('visits a route with an encoded slash', '/encoded/AC%2fDC', async ({ page }) => { + assert.equal(await page.innerHTML('h2'), '/encoded/AC%2fDC: AC/DC'); + assert.equal(await page.innerHTML('h3'), '/encoded/AC%2fDC: AC/DC'); + }); + test( 'visits a dynamic route with non-ASCII character', '/encoded',