From fd7f27f4c54af9b5874300c961c05d9ce28994b5 Mon Sep 17 00:00:00 2001 From: antoine Date: Mon, 22 Jul 2024 18:50:36 +0200 Subject: [PATCH 1/2] Escape special regex characters when matching routes --- src/js/Route.js | 1 + tests/js/route.test.js | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/src/js/Route.js b/src/js/Route.js index b3b44532..ea24493b 100644 --- a/src/js/Route.js +++ b/src/js/Route.js @@ -80,6 +80,7 @@ export default class Route { // Transform the route's template into a regex that will match a hydrated URL, // by replacing its parameter segments with matchers for parameter values const pattern = this.template + .replace(/[.*+^$()|[\]]/g, '\\$&') .replace(/(\/?){([^}?]*)(\??)}/g, (_, slash, segment, optional) => { const regex = `(?<${segment}>${ this.wheres[segment]?.replace(/(^\^)|(\$$)/g, '') || '[^/?]+' diff --git a/tests/js/route.test.js b/tests/js/route.test.js index 78b2d423..d960d56e 100644 --- a/tests/js/route.test.js +++ b/tests/js/route.test.js @@ -261,6 +261,10 @@ const defaultZiggy = { }, parameters: ['storefront', 'catalog_uri'], }, + regexSpecialChars: { + uri: 'test.*+^$()|[]/{slug}', + methods: ['GET', 'HEAD'], + }, }, }; @@ -1439,6 +1443,13 @@ describe('current()', () => { expect(route().current('events.venues.*')).toBe(false); }); + test('matches route with escaped Regex special characters', () => { + global.window.location.pathname = '/test.*+^$()|[]/1'; + + expect(route().current()).toBe('regexSpecialChars'); + expect(route().current('regexSpecialChars')).toBe(true); + }); + test.skip('can unresolve arbitrary urls to names and params', () => { const resolved = route().unresolve('https://ziggy.dev/events/1/venues?test=yes'); expect(resolved).toStrictEqual({ From 581f58c6d01712e2b9a38c2a84cd12b1b418d9b0 Mon Sep 17 00:00:00 2001 From: Jacob Baker-Kretzmar Date: Sat, 3 Aug 2024 17:03:50 -0400 Subject: [PATCH 2/2] Remove `^` and `|` --- src/js/Route.js | 2 +- tests/js/route.test.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/js/Route.js b/src/js/Route.js index ea24493b..eb8084c0 100644 --- a/src/js/Route.js +++ b/src/js/Route.js @@ -80,7 +80,7 @@ export default class Route { // Transform the route's template into a regex that will match a hydrated URL, // by replacing its parameter segments with matchers for parameter values const pattern = this.template - .replace(/[.*+^$()|[\]]/g, '\\$&') + .replace(/[.*+$()[\]]/g, '\\$&') .replace(/(\/?){([^}?]*)(\??)}/g, (_, slash, segment, optional) => { const regex = `(?<${segment}>${ this.wheres[segment]?.replace(/(^\^)|(\$$)/g, '') || '[^/?]+' diff --git a/tests/js/route.test.js b/tests/js/route.test.js index d960d56e..e530280d 100644 --- a/tests/js/route.test.js +++ b/tests/js/route.test.js @@ -262,7 +262,7 @@ const defaultZiggy = { parameters: ['storefront', 'catalog_uri'], }, regexSpecialChars: { - uri: 'test.*+^$()|[]/{slug}', + uri: 'test.*+$()[]/{slug}', methods: ['GET', 'HEAD'], }, }, @@ -1444,7 +1444,7 @@ describe('current()', () => { }); test('matches route with escaped Regex special characters', () => { - global.window.location.pathname = '/test.*+^$()|[]/1'; + global.window.location.pathname = '/test.*+$()[]/1'; expect(route().current()).toBe('regexSpecialChars'); expect(route().current('regexSpecialChars')).toBe(true);