diff --git a/src/plugins/router/RoutePattern.js b/src/plugins/router/RoutePattern.js index 9982b9d..9f99e46 100644 --- a/src/plugins/router/RoutePattern.js +++ b/src/plugins/router/RoutePattern.js @@ -52,7 +52,7 @@ const default_constraints = Object.freeze({ "length"(value) { let values = value.split(",").map(v => v.trim()); return { - test: values.length == 2 + test: values.length === 2 ? v => v.length >= +values[0] && v.length <= +values[1] : v => v.length === +values[0] }; @@ -174,8 +174,11 @@ export class RoutePattern { } if (part.catch_all) { - value = as_array(value); - parts.push(...value.map(v => encodeURIComponent(v)).join("/")); + value = as_array(value).map(v => encodeURIComponent(v)).join("/"); + + // an empty catch-all value adds nothing, + // so a segment consisting of it alone is omitted + value && parts.push(value); } else { parts.push(encodeURIComponent(value)); diff --git a/tests/utilities/RoutePattern.test.js b/tests/utilities/RoutePattern.test.js index 7a6fcb0..bf506d3 100644 --- a/tests/utilities/RoutePattern.test.js +++ b/tests/utilities/RoutePattern.test.js @@ -412,6 +412,13 @@ describe("RoutePattern", () => { expect(route.match("/abcdef")).toBeNull(); }); + test("resolve: /files/{path*}", () => { + const route = new RoutePattern("/files/{path*}"); + expect(route.resolve({ path: ["a", "b c", "d/e"] })).toBe("/files/a/b%20c/d%2Fe"); + expect(route.resolve({ path: [] })).toBe("/files"); + expect(route.resolve({})).toBe("/files"); + }); + test("error: unclosed brace parameter", () => { assert.throws(() => new RoutePattern("/{id"), "Invalid pattern: /{id"); assert.throws(() => new RoutePattern("/{id}/{"), "Invalid pattern: /{");