From d2ff35551c1fab084a330031853c5707d1b716a9 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Wed, 18 Jan 2023 11:37:46 -0500 Subject: [PATCH] Remove dependency on url-parse due to side effects Signed-off-by: Sebastian Malton --- package.json | 3 --- src/common/protocol-handler/error.ts | 5 ++--- src/common/protocol-handler/router.ts | 15 +++++++-------- .../create-context-handler.injectable.ts | 3 +-- .../shell-api-request.injectable.ts | 6 ++++-- .../lens-protocol-router-main.ts | 13 ++++++------- .../utils/get-port-from-stream.injectable.ts | 3 +-- .../attempt-install-by-info.injectable.tsx | 3 +-- .../lens-protocol-router-renderer.tsx | 5 ++--- yarn.lock | 18 ------------------ 10 files changed, 24 insertions(+), 50 deletions(-) diff --git a/package.json b/package.json index 4d08fa57c5..54a5054009 100644 --- a/package.json +++ b/package.json @@ -294,7 +294,6 @@ "tcp-port-used": "^1.0.2", "tempy": "1.0.1", "typed-regex": "^0.0.8", - "url-parse": "^1.5.10", "uuid": "^8.3.2", "win-ca": "^3.5.0", "winston": "^3.8.2", @@ -361,7 +360,6 @@ "@types/tcp-port-used": "^1.0.1", "@types/tempy": "^0.3.0", "@types/triple-beam": "^1.3.2", - "@types/url-parse": "^1.4.8", "@types/uuid": "^8.3.4", "@types/webpack": "^5.28.0", "@types/webpack-dev-server": "^4.7.2", @@ -460,7 +458,6 @@ "@types/react-window": "^1.8.5", "@types/tar": "^6.1.3", "@types/tcp-port-used": "^1.0.1", - "@types/url-parse": "^1.4.8", "@types/uuid": "^8.3.4", "monaco-editor": "^0.29.1", "react-select": "^5.7.0", diff --git a/src/common/protocol-handler/error.ts b/src/common/protocol-handler/error.ts index 707c8d420b..03f790f563 100644 --- a/src/common/protocol-handler/error.ts +++ b/src/common/protocol-handler/error.ts @@ -3,7 +3,6 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type Url from "url-parse"; export enum RoutingErrorType { INVALID_PROTOCOL = "invalid-protocol", @@ -14,13 +13,13 @@ export enum RoutingErrorType { MISSING_EXTENSION = "missing-ext", } -export class RoutingError extends Error { +export class RoutingError extends Error { /** * Will be set if the routing error originated in an extension route table */ public extensionName?: string; - constructor(public type: RoutingErrorType, public url: Url) { + constructor(public type: RoutingErrorType, public url: URL) { super("routing error"); } diff --git a/src/common/protocol-handler/router.ts b/src/common/protocol-handler/router.ts index 8c9915b287..be996061e0 100644 --- a/src/common/protocol-handler/router.ts +++ b/src/common/protocol-handler/router.ts @@ -8,7 +8,6 @@ import { matchPath } from "react-router"; import { countBy } from "lodash"; import { isDefined, iter } from "../utils"; import { pathToRegexp } from "path-to-regexp"; -import type Url from "url-parse"; import { RoutingError, RoutingErrorType } from "./error"; import type { ExtensionsStore } from "../../extensions/extensions-store/extensions-store"; import type { ExtensionLoader } from "../../extensions/extension-loader"; @@ -84,7 +83,7 @@ export abstract class LensProtocolRouter { * @param url the parsed URL that initiated the `lens://` protocol * @returns true if a route has been found */ - protected _routeToInternal(url: Url>): RouteAttempt { + protected _routeToInternal(url: URL): RouteAttempt { return this._route(this.internalRoutes.entries(), url); } @@ -94,7 +93,7 @@ export abstract class LensProtocolRouter { * @param routes the array of path schemas, handler pairs to match against * @param url the url (in its current state) */ - protected _findMatchingRoute(routes: Iterable<[string, RouteHandler]>, url: Url>): null | [match>, RouteHandler] { + protected _findMatchingRoute(routes: Iterable<[string, RouteHandler]>, url: URL): null | [match>, RouteHandler] { const matches: [match>, RouteHandler][] = []; for (const [schema, handler] of routes) { @@ -131,7 +130,7 @@ export abstract class LensProtocolRouter { * @param routes the array of (path schemas, handler) pairs to match against * @param url the url (in its current state) */ - protected _route(routes: Iterable<[string, RouteHandler]>, url: Url>, extensionName?: string): RouteAttempt { + protected _route(routes: Iterable<[string, RouteHandler]>, url: URL, extensionName?: string): RouteAttempt { const route = this._findMatchingRoute(routes, url); if (!route) { @@ -150,7 +149,7 @@ export abstract class LensProtocolRouter { const params: RouteParams = { pathname: match.params, - search: url.query, + search: Object.fromEntries(url.searchParams.entries()), }; if (!match.isExact) { @@ -169,7 +168,7 @@ export abstract class LensProtocolRouter { * @param url the protocol request URI that was "open"-ed * @returns either the found name or the instance of `LensExtension` */ - protected async _findMatchingExtensionByName(url: Url>): Promise { + protected async _findMatchingExtensionByName(url: URL): Promise { interface ExtensionUrlMatch { [EXTENSION_PUBLISHER_MATCH]: string; [EXTENSION_NAME_MATCH]: string; @@ -230,7 +229,7 @@ export abstract class LensProtocolRouter { * Note: this function modifies its argument, do not reuse * @param url the protocol request URI that was "open"-ed */ - protected async _routeToExtension(url: Url>): Promise { + protected async _routeToExtension(url: URL): Promise { const extension = await this._findMatchingExtensionByName(url); if (typeof extension === "string") { @@ -239,7 +238,7 @@ export abstract class LensProtocolRouter { } // remove the extension name from the path name so we don't need to match on it anymore - url.set("pathname", url.pathname.slice(extension.name.length + 1)); + url.pathname = url.pathname.slice(extension.name.length + 1); try { const handlers = iter.map(extension.protocolHandlers, ({ pathSchema, handler }) => [pathSchema, handler] as [string, RouteHandler]); diff --git a/src/main/context-handler/create-context-handler.injectable.ts b/src/main/context-handler/create-context-handler.injectable.ts index 57ca9bd38b..84af37a620 100644 --- a/src/main/context-handler/create-context-handler.injectable.ts +++ b/src/main/context-handler/create-context-handler.injectable.ts @@ -8,7 +8,6 @@ import type { ClusterContextHandler, ContextHandlerDependencies } from "./contex import { ContextHandler } from "./context-handler"; import createKubeAuthProxyInjectable from "../kube-auth-proxy/create-kube-auth-proxy.injectable"; import kubeAuthProxyCertificateInjectable from "../kube-auth-proxy/kube-auth-proxy-certificate.injectable"; -import URLParse from "url-parse"; import getPrometheusProviderByKindInjectable from "../prometheus/get-by-kind.injectable"; import prometheusProvidersInjectable from "../prometheus/providers.injectable"; import loggerInjectable from "../../common/logger.injectable"; @@ -27,7 +26,7 @@ const createContextHandlerInjectable = getInjectable({ }; return (cluster: Cluster): ClusterContextHandler => { - const clusterUrl = new URLParse(cluster.apiUrl); + const clusterUrl = new URL(cluster.apiUrl); return new ContextHandler({ ...dependencies, diff --git a/src/main/lens-proxy/upgrade-router/shell-api-request.injectable.ts b/src/main/lens-proxy/upgrade-router/shell-api-request.injectable.ts index 226f697b9c..ea54b43113 100644 --- a/src/main/lens-proxy/upgrade-router/shell-api-request.injectable.ts +++ b/src/main/lens-proxy/upgrade-router/shell-api-request.injectable.ts @@ -5,7 +5,6 @@ import { getInjectable } from "@ogre-tools/injectable"; import authenticateShellRequestInjectable from "./shell-request-authenticator.injectable"; import openShellSessionInjectable from "../../shell-session/create-shell-session.injectable"; -import URLParse from "url-parse"; import { Server as WebSocketServer } from "ws"; import loggerInjectable from "../../../common/logger.injectable"; import getClusterForRequestInjectable from "../get-cluster-for-request.injectable"; @@ -24,7 +23,10 @@ const shellApiUpgradeRouteInjectable = getInjectable({ return { handler: ({ req, socket, head }) => { const cluster = getClusterForRequest(req); - const { query: { node: nodeName, shellToken, id: tabId }} = new URLParse(req.url, true); + const { searchParams } = new URL(req.url, "https://lens.app"); + const nodeName = searchParams.get("node") ?? undefined; + const shellToken = searchParams.get("shellToken") ?? undefined; + const tabId = searchParams.get("id"); if (!tabId || !cluster || !authenticateShellRequest(cluster.id, tabId, shellToken)) { socket.write("Invalid shell request"); diff --git a/src/main/protocol-handler/lens-protocol-router-main/lens-protocol-router-main.ts b/src/main/protocol-handler/lens-protocol-router-main/lens-protocol-router-main.ts index 3beb596e4e..4be2d3953b 100644 --- a/src/main/protocol-handler/lens-protocol-router-main/lens-protocol-router-main.ts +++ b/src/main/protocol-handler/lens-protocol-router-main/lens-protocol-router-main.ts @@ -4,7 +4,6 @@ */ import * as proto from "../../../common/protocol-handler"; -import URLParse from "url-parse"; import type { LensExtension } from "../../../extensions/lens-extension"; import { observable, when, makeObservable } from "mobx"; import type { LensProtocolRouterDependencies, RouteAttempt } from "../../../common/protocol-handler"; @@ -22,7 +21,7 @@ export interface FallbackHandler { * @returns `true` if it should be routed internally to Lens, `false` if to an extension * @throws if `host` is not valid */ -function checkHost(url: URLParse): boolean { +function checkHost(url: URL): boolean { switch (url.host) { case "app": return true; @@ -64,7 +63,7 @@ export class LensProtocolRouterMain extends proto.LensProtocolRouter { */ public async route(rawUrl: string) { try { - const url = new URLParse(rawUrl, true); + const url = new URL(rawUrl); if (url.protocol.toLowerCase() !== "lens:") { throw new proto.RoutingError(proto.RoutingErrorType.INVALID_PROTOCOL, url); @@ -101,7 +100,7 @@ export class LensProtocolRouterMain extends proto.LensProtocolRouter { return false; } - protected async _findMatchingExtensionByName(url: URLParse>): Promise { + protected async _findMatchingExtensionByName(url: URL): Promise { const firstAttempt = await super._findMatchingExtensionByName(url); if (typeof firstAttempt !== "string") { @@ -115,7 +114,7 @@ export class LensProtocolRouterMain extends proto.LensProtocolRouter { return ""; } - protected _routeToInternal(url: URLParse>): RouteAttempt { + protected _routeToInternal(url: URL): RouteAttempt { const rawUrl = url.toString(); // for sending to renderer const attempt = super._routeToInternal(url); @@ -124,7 +123,7 @@ export class LensProtocolRouterMain extends proto.LensProtocolRouter { return attempt; } - protected async _routeToExtension(url: URLParse>): Promise { + protected async _routeToExtension(url: URL): Promise { const rawUrl = url.toString(); // for sending to renderer /** @@ -134,7 +133,7 @@ export class LensProtocolRouterMain extends proto.LensProtocolRouter { * Note: this needs to clone the url because _routeToExtension modifies its * argument. */ - const attempt = await super._routeToExtension(new URLParse(url.toString(), true)); + const attempt = await super._routeToExtension(new URL(url.toString())); this.disposers.push(when(() => this.rendererLoaded, () => this.dependencies.broadcastMessage(proto.ProtocolHandlerExtension, rawUrl, attempt))); diff --git a/src/main/utils/get-port-from-stream.injectable.ts b/src/main/utils/get-port-from-stream.injectable.ts index 983ed66313..3b36766cda 100644 --- a/src/main/utils/get-port-from-stream.injectable.ts +++ b/src/main/utils/get-port-from-stream.injectable.ts @@ -4,7 +4,6 @@ */ import type { Readable } from "stream"; -import URLParse from "url-parse"; import { getInjectable } from "@ogre-tools/injectable"; import loggerInjectable from "../../common/logger.injectable"; @@ -53,7 +52,7 @@ const getPortFromStreamInjectable = getInjectable({ if (match.matched) { // use unknown protocol so that there is no default port - const addr = new URLParse(`s://${match.groups?.address?.trim()}`); + const addr = new URL(`s://${match.groups?.address?.trim()}`); args.onFind?.(); stream.off("data", handler); diff --git a/src/renderer/components/+extensions/attempt-install-by-info.injectable.tsx b/src/renderer/components/+extensions/attempt-install-by-info.injectable.tsx index 1f3d65c802..945883620e 100644 --- a/src/renderer/components/+extensions/attempt-install-by-info.injectable.tsx +++ b/src/renderer/components/+extensions/attempt-install-by-info.injectable.tsx @@ -5,7 +5,6 @@ import { isObject } from "../../../common/utils"; import React from "react"; import { SemVer } from "semver"; -import URLParse from "url-parse"; import { getInjectable } from "@ogre-tools/injectable"; import attemptInstallInjectable from "./attempt-install/attempt-install.injectable"; import getBaseRegistryUrlInjectable from "./get-base-registry-url/get-base-registry-url.injectable"; @@ -58,7 +57,7 @@ const attemptInstallByInfoInjectable = getInjectable({ const { name, version: versionOrTagName, requireConfirmation = false } = info; const disposer = extensionInstallationStateStore.startPreInstall(); const baseUrl = await getBaseRegistryUrl(); - const registryUrl = new URLParse(baseUrl).set("pathname", name).toString(); + const registryUrl = new URL(name, baseUrl).toString(); let json: NpmRegistryPackageDescriptor; try { diff --git a/src/renderer/protocol-handler/lens-protocol-router-renderer/lens-protocol-router-renderer.tsx b/src/renderer/protocol-handler/lens-protocol-router-renderer/lens-protocol-router-renderer.tsx index 3c9959aa87..2dc5f16e1f 100644 --- a/src/renderer/protocol-handler/lens-protocol-router-renderer/lens-protocol-router-renderer.tsx +++ b/src/renderer/protocol-handler/lens-protocol-router-renderer/lens-protocol-router-renderer.tsx @@ -6,7 +6,6 @@ import React from "react"; import { ipcRenderer } from "electron"; import * as proto from "../../../common/protocol-handler"; -import Url from "url-parse"; import type { LensProtocolRouterDependencies } from "../../../common/protocol-handler"; import { foldAttemptResults, ProtocolHandlerInvalid, RouteAttempt } from "../../../common/protocol-handler"; import type { ShowNotification } from "../../components/notifications"; @@ -26,7 +25,7 @@ export class LensProtocolRouterRenderer extends proto.LensProtocolRouter { */ public init(): void { ipcRenderer.on(proto.ProtocolHandlerInternal, (event, rawUrl: string, mainAttemptResult: RouteAttempt) => { - const rendererAttempt = this._routeToInternal(new Url(rawUrl, true)); + const rendererAttempt = this._routeToInternal(new URL(rawUrl)); if (foldAttemptResults(mainAttemptResult, rendererAttempt) === RouteAttempt.MISSING) { this.dependencies.showShortInfoNotification(( @@ -39,7 +38,7 @@ export class LensProtocolRouterRenderer extends proto.LensProtocolRouter { } }); ipcRenderer.on(proto.ProtocolHandlerExtension, async (event, rawUrl: string, mainAttemptResult: RouteAttempt) => { - const rendererAttempt = await this._routeToExtension(new Url(rawUrl, true)); + const rendererAttempt = await this._routeToExtension(new URL(rawUrl)); switch (foldAttemptResults(mainAttemptResult, rendererAttempt)) { case RouteAttempt.MISSING: diff --git a/yarn.lock b/yarn.lock index c8f38ae883..e018bd7439 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2779,11 +2779,6 @@ dependencies: source-map "^0.6.1" -"@types/url-parse@^1.4.8": - version "1.4.8" - resolved "https://registry.yarnpkg.com/@types/url-parse/-/url-parse-1.4.8.tgz#c3825047efbca1295b7f1646f38203d9145130d6" - integrity sha512-zqqcGKyNWgTLFBxmaexGUKQyWqeG7HjXj20EuQJSJWwXe54BjX0ihIo5cJB9yAQzH8dNugJ9GvkBYMjPXs/PJw== - "@types/uuid@^8.3.4": version "8.3.4" resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.4.tgz#bd86a43617df0594787d38b735f55c805becf1bc" @@ -11090,11 +11085,6 @@ query-string@^7.1.3: split-on-first "^1.0.0" strict-uri-encode "^2.0.0" -querystringify@^2.1.1: - version "2.2.0" - resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" - integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== - queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" @@ -13291,14 +13281,6 @@ url-parse-lax@^3.0.0: dependencies: prepend-http "^2.0.0" -url-parse@^1.5.10: - version "1.5.10" - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" - integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== - dependencies: - querystringify "^2.1.1" - requires-port "^1.0.0" - url-to-options@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9"