diff --git a/src/js/Route.js b/src/js/Route.js index f17c82d3..7fd6a347 100644 --- a/src/js/Route.js +++ b/src/js/Route.js @@ -113,13 +113,9 @@ export default class Route { if (!new RegExp(`^${optional ? `(${this.wheres[segment]})?` : this.wheres[segment]}$`).test(params[segment] ?? '')) { throw new Error(`Ziggy error: '${segment}' parameter does not match required format '${this.wheres[segment]}' for route '${this.name}'.`) } - - if (segments[segments.length - 1].name === segment) { - return encodeURIComponent(params[segment] ?? '').replace(/%2F/g, '/'); - } } - return encodeURIComponent(params[segment] ?? ''); + return encodeURI(params[segment] ?? '').replace(/%7C/g, '|').replace(/%25/g, '%').replace(/\$/g, '%24'); }).replace(`${this.origin}//`, `${this.origin}/`).replace(/\/+$/, ''); } } diff --git a/tests/js/route.test.js b/tests/js/route.test.js index e93ca0be..d89db677 100644 --- a/tests/js/route.test.js +++ b/tests/js/route.test.js @@ -205,14 +205,6 @@ const defaultZiggy = { slug: '.+', }, }, - slashesMiddleParam: { - uri: 'slashes/{encoded}/{slug}', - methods: ['GET', 'HEAD'], - wheres: { - encoded: '.+', - slug: '.+', - }, - }, }, }; @@ -479,19 +471,19 @@ describe('route()', () => { same(route('events.venues.index', 1), 'https://test.thing/ab/cd/events/1/venues'); }); - test('can URL-encode named parameters', () => { + test('URL-encode query parameters', () => { global.Ziggy.url = 'https://test.thing/ab/cd'; same( route('events.venues.index', { event: 'Fun&Games' }), - 'https://test.thing/ab/cd/events/Fun%26Games/venues' + 'https://test.thing/ab/cd/events/Fun&Games/venues' ); same( route('events.venues.index', { event: 'Fun&Games', location: 'Blues&Clues', }), - 'https://test.thing/ab/cd/events/Fun%26Games/venues?location=Blues%26Clues' + 'https://test.thing/ab/cd/events/Fun&Games/venues?location=Blues%26Clues' ); }); @@ -638,19 +630,34 @@ describe('route()', () => { }); test('skip encoding slashes inside last parameter when explicitly allowed', () => { - same(route('slashes', ['one/two', 'three/four']), 'https://ziggy.dev/slashes/one%2Ftwo/three/four'); - same(route('slashes', ['one/two', 'Fun&Games/venues']), 'https://ziggy.dev/slashes/one%2Ftwo/Fun%26Games/venues'); - same(route('slashes', ['one/two/three', 'Fun&Games/venues/outdoors']), 'https://ziggy.dev/slashes/one%2Ftwo%2Fthree/Fun%26Games/venues/outdoors'); - - same(route('slashesOtherRegex', ['one/two', 'three/four']), 'https://ziggy.dev/slashes/one%2Ftwo/three/four'); - same(route('slashesOtherRegex', ['one/two', 'Fun&Games/venues']), 'https://ziggy.dev/slashes/one%2Ftwo/Fun%26Games/venues'); - same(route('slashesOtherRegex', ['one/two/three', 'Fun&Games/venues/outdoors']), 'https://ziggy.dev/slashes/one%2Ftwo%2Fthree/Fun%26Games/venues/outdoors'); - }); - - test.skip('skip encoding slashes inside middle parameter when explicitly allowed', () => { - same(route('slashesMiddleParam', ['one/two', 'three/four']), 'https://ziggy.dev/slashes/one/two/three/four'); - same(route('slashesMiddleParam', ['one/two', 'Fun&Games/venues']), 'https://ziggy.dev/slashes/one/two/Fun%26Games/venues'); - same(route('slashesMiddleParam', ['one/two/three', 'Fun&Games/venues/outdoors']), 'https://ziggy.dev/slashes/one/two/three/Fun%26Games/venues/outdoors'); + same(route('slashes', ['one/two', 'three/four']), 'https://ziggy.dev/slashes/one/two/three/four'); + same(route('slashes', ['one/two', 'Fun&Games/venues']), 'https://ziggy.dev/slashes/one/two/Fun&Games/venues'); + same(route('slashes', ['one/two/three', 'Fun&Games/venues/outdoors']), 'https://ziggy.dev/slashes/one/two/three/Fun&Games/venues/outdoors'); + + same(route('slashesOtherRegex', ['one/two', 'three/four']), 'https://ziggy.dev/slashes/one/two/three/four'); + same(route('slashesOtherRegex', ['one/two', 'Fun&Games/venues']), 'https://ziggy.dev/slashes/one/two/Fun&Games/venues'); + same(route('slashesOtherRegex', ['one/two/three', 'Fun&Games/venues/outdoors']), 'https://ziggy.dev/slashes/one/two/three/Fun&Games/venues/outdoors'); + }); + + test('skip encoding some characters in route parameters', () => { + // Laravel doesn't encode these characters in route parameters: / @ : ; , = + ! * | ? & # % + same(route('pages', 'a/b'), 'https://ziggy.dev/a/b'); + same(route('pages', 'a@b'), 'https://ziggy.dev/a@b'); + same(route('pages', 'a:b'), 'https://ziggy.dev/a:b'); + same(route('pages', 'a;b'), 'https://ziggy.dev/a;b'); + same(route('pages', 'a,b'), 'https://ziggy.dev/a,b'); + same(route('pages', 'a=b'), 'https://ziggy.dev/a=b'); + same(route('pages', 'a+b'), 'https://ziggy.dev/a+b'); + same(route('pages', 'a!b'), 'https://ziggy.dev/a!b'); + same(route('pages', 'a*b'), 'https://ziggy.dev/a*b'); + same(route('pages', 'a|b'), 'https://ziggy.dev/a|b'); + same(route('pages', 'a?b'), 'https://ziggy.dev/a?b'); + same(route('pages', 'a&b'), 'https://ziggy.dev/a&b'); + same(route('pages', 'a#b'), 'https://ziggy.dev/a#b'); + same(route('pages', 'a%b'), 'https://ziggy.dev/a%b'); + + // Laravel does encode '$', but encodeURI() doesn't + same(route('pages', 'a$b'), 'https://ziggy.dev/a%24b'); }); });