diff --git a/src/main/protocol-handler/__test__/router.test.ts b/src/main/protocol-handler/__test__/router.test.ts index 17fb4e1b01..0052775b71 100644 --- a/src/main/protocol-handler/__test__/router.test.ts +++ b/src/main/protocol-handler/__test__/router.test.ts @@ -1,5 +1,6 @@ import { LensProtocolRouter } from "../router"; import Url from "url-parse"; +import { noop } from "../../../common/utils"; describe("protocol router tests", () => { let lpr: LensProtocolRouter; @@ -18,7 +19,41 @@ describe("protocol router tests", () => { }); it("should not throw when has valid host", () => { + lpr.on("/", noop); + lpr.extensionOn("minikube", "/", noop); + expect(() => lpr.route(Url("lens://internal"))).not.toThrowError(); - expect(() => lpr.route(Url("lens://extension"))).not.toThrowError(); + expect(() => lpr.route(Url("lens://extension/minikube"))).not.toThrowError(); + }); + + it("should call handler if matches", () => { + let called = false; + + lpr.on("/page", () => { called = true; }); + expect(() => lpr.route(Url("lens://internal/page"))).not.toThrowError(); + expect(called).toBe(true); + }); + + it("should call most exact handler", () => { + let called: any = 0; + + lpr.on("/page", () => { called = 1; }); + lpr.on("/page/:id", params => { called = params.pathname.id; }); + expect(() => lpr.route(Url("lens://internal/page/foo"))).not.toThrowError(); + expect(called).toBe("foo"); + }); + + it("should call most exact handler for an extensions", () => { + let called: any = 0; + + lpr.extensionOn("foobar", "/page", () => { called = 1; }); + lpr.extensionOn("foobar", "/page/:id", params => { called = params.pathname.id; }); + expect(() => lpr.route(Url("lens://extension/foobar/page/foob"))).not.toThrowError(); + expect(called).toBe("foob"); + }); + + it("should throw if urlSchema is invalid", () => { + expect(() => lpr.on("/:@", noop)).toThrowError(); + expect(() => lpr.extensionOn("foobar", "/page/:@", noop)).toThrowError(); }); }); diff --git a/src/main/protocol-handler/router.ts b/src/main/protocol-handler/router.ts index 08b1769d11..f89f6f69da 100644 --- a/src/main/protocol-handler/router.ts +++ b/src/main/protocol-handler/router.ts @@ -1,6 +1,7 @@ import { Singleton } from "../../common/utils"; import Url from "url-parse"; import { match, matchPath } from "react-router"; +import { pathToRegexp } from "path-to-regexp"; export enum RoutingErrorType { INVALID_PROTOCOL = "invalid-protocol", @@ -53,7 +54,7 @@ export class LensProtocolRouter extends Singleton { private extentionRoutes = new Map>(); private internalRoutes = new Map(); - private static ExtensionIDSchema = `/:${EXT_ID_MATCH}/`; + private static ExtensionIDSchema = `/:${EXT_ID_MATCH}`; /** * route @@ -75,7 +76,7 @@ export class LensProtocolRouter extends Singleton { } private _routeToExtension(url: Url): void { - const match = matchPath(url.pathname, { path: LensProtocolRouter.ExtensionIDSchema }); + const match = matchPath(url.pathname, LensProtocolRouter.ExtensionIDSchema); if (!match) { throw new RoutingError(RoutingErrorType.NO_EXTENSION_ID, url); @@ -94,9 +95,13 @@ export class LensProtocolRouter extends Singleton { private _route(routes: Map, url: Url, matchExtension = false): void { const matches = Array.from(routes.entries()) .map(([schema, handler]): [match>, RouteHandler] => { - const path = `${matchExtension ? LensProtocolRouter.ExtensionIDSchema : ""}${schema}`; + if (matchExtension) { + const joinChar = schema.startsWith("/") ? "" : "/"; - return [matchPath(url.pathname, { path }), handler]; + schema = `${LensProtocolRouter.ExtensionIDSchema}${joinChar}${schema}`; + } + + return [matchPath(url.pathname, { path: schema }), handler]; }) .filter(([match]) => match); // prefer an exact match, but if not pick the first route registered @@ -116,10 +121,13 @@ export class LensProtocolRouter extends Singleton { } public on(urlSchema: string, handler: RouteHandler): void { + pathToRegexp(urlSchema); // verify now that the schema is valid this.internalRoutes.set(urlSchema, handler); } public extensionOn(id: ExtensionId, urlSchema: string, handler: RouteHandler): void { + pathToRegexp(urlSchema); // verify now that the schema is valid + if (!this.extentionRoutes.has(id)) { this.extentionRoutes.set(id, new Map()); }