Remove url npm dependency and use Web URL constructor (#10930)

This commit is contained in:
Michael Telatynski 2023-05-17 12:50:00 +01:00 committed by GitHub
parent 7917d973e7
commit 2da199c41d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 101 additions and 53 deletions

View file

@ -14,7 +14,6 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import url from "url";
import { SERVICE_TYPES } from "matrix-js-sdk/src/service-types";
import { Room } from "matrix-js-sdk/src/models/room";
import { logger } from "matrix-js-sdk/src/logger";
@ -25,6 +24,7 @@ import { Service, startTermsFlow, TermsInteractionCallback, TermsNotSignedError
import { MatrixClientPeg } from "./MatrixClientPeg";
import SdkConfig from "./SdkConfig";
import { WidgetType } from "./widgets/WidgetType";
import { parseUrl } from "./utils/UrlUtils";
// The version of the integration manager API we're intending to work with
const imApiVersion = "1.1";
@ -154,11 +154,10 @@ export default class ScalarAuthClient {
// Once we've fully transitioned to _matrix URLs, we can give people
// a grace period to update their configs, then use the rest url as
// a regular base url.
const parsedImRestUrl = url.parse(this.apiUrl);
parsedImRestUrl.path = "";
const parsedImRestUrl = parseUrl(this.apiUrl);
parsedImRestUrl.pathname = "";
return startTermsFlow(
[new Service(SERVICE_TYPES.IM, url.format(parsedImRestUrl), token)],
[new Service(SERVICE_TYPES.IM, parsedImRestUrl.toString(), token)],
this.termsInteractionCallback,
).then(() => {
return token;

View file

@ -14,7 +14,6 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import url from "url";
import React from "react";
import { SERVICE_TYPES } from "matrix-js-sdk/src/service-types";
@ -23,6 +22,7 @@ import DialogButtons from "../elements/DialogButtons";
import BaseDialog from "./BaseDialog";
import { ServicePolicyPair } from "../../../Terms";
import ExternalLink from "../elements/ExternalLink";
import { parseUrl } from "../../../utils/UrlUtils";
interface ITermsCheckboxProps {
onChange: (url: string, checked: boolean) => void;
@ -130,7 +130,7 @@ export default class TermsDialog extends React.PureComponent<ITermsDialogProps,
public render(): React.ReactNode {
const rows: JSX.Element[] = [];
for (const policiesAndService of this.props.policiesAndServicePairs) {
const parsedBaseUrl = url.parse(policiesAndService.service.baseUrl);
const parsedBaseUrl = parseUrl(policiesAndService.service.baseUrl);
const policyValues = Object.values(policiesAndService.policies);
for (let i = 0; i < policyValues.length; ++i) {

View file

@ -17,7 +17,6 @@ limitations under the License.
*/
import React from "react";
import url from "url";
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
import { _t } from "../../../languageHandler";
@ -28,6 +27,7 @@ import MemberAvatar from "../avatars/MemberAvatar";
import BaseAvatar from "../avatars/BaseAvatar";
import AccessibleButton from "./AccessibleButton";
import TextWithTooltip from "./TextWithTooltip";
import { parseUrl } from "../../../utils/UrlUtils";
interface IProps {
url: string;
@ -67,13 +67,12 @@ export default class AppPermission extends React.Component<IProps, IState> {
}
private parseWidgetUrl(): { isWrapped: boolean; widgetDomain: string | null } {
const widgetUrl = url.parse(this.props.url);
const params = new URLSearchParams(widgetUrl.search ?? undefined);
const widgetUrl = parseUrl(this.props.url);
// HACK: We're relying on the query params when we should be relying on the widget's `data`.
// This is a workaround for Scalar.
if (WidgetUtils.isScalarUrl(this.props.url) && params?.get("url")) {
const unwrappedUrl = url.parse(params.get("url")!);
if (WidgetUtils.isScalarUrl(this.props.url) && widgetUrl.searchParams.has("url")) {
const unwrappedUrl = parseUrl(widgetUrl.searchParams.get("url")!);
return {
widgetDomain: unwrappedUrl.host || unwrappedUrl.hostname,
isWrapped: true,

View file

@ -17,7 +17,6 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import url from "url";
import React, { ContextType, createRef, CSSProperties, MutableRefObject, ReactNode } from "react";
import classNames from "classnames";
import { IWidget, MatrixCapabilities } from "matrix-widget-api";
@ -52,6 +51,7 @@ import { ElementWidgetCapabilities } from "../../../stores/widgets/ElementWidget
import { WidgetMessagingStore } from "../../../stores/widgets/WidgetMessagingStore";
import { SdkContextClass } from "../../../contexts/SDKContext";
import { ModuleRunner } from "../../../modules/ModuleRunner";
import { parseUrl } from "../../../utils/UrlUtils";
interface IProps {
app: IWidget | IApp;
@ -265,7 +265,7 @@ export default class AppTile extends React.Component<IProps, IState> {
private isMixedContent(): boolean {
const parentContentProtocol = window.location.protocol;
const u = url.parse(this.props.app.url);
const u = parseUrl(this.props.app.url);
const childContentProtocol = u.protocol;
if (parentContentProtocol === "https:" && childContentProtocol !== "https:") {
logger.warn(

View file

@ -14,7 +14,6 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import url from "url";
import React, { ReactNode } from "react";
import { logger } from "matrix-js-sdk/src/logger";
import { IThreepid } from "matrix-js-sdk/src/@types/threepids";
@ -25,7 +24,7 @@ import Modal from "../../../Modal";
import dis from "../../../dispatcher/dispatcher";
import { getThreepidsWithBindStatus } from "../../../boundThreepids";
import IdentityAuthClient from "../../../IdentityAuthClient";
import { abbreviateUrl, unabbreviateUrl } from "../../../utils/UrlUtils";
import { abbreviateUrl, parseUrl, unabbreviateUrl } from "../../../utils/UrlUtils";
import { getDefaultIdentityServerUrl, doesIdentityServerHaveTerms } from "../../../utils/IdentityServerUtils";
import { timeout } from "../../../utils/promise";
import { ActionPayload } from "../../../dispatcher/payloads";
@ -44,7 +43,7 @@ const REACHABILITY_TIMEOUT = 10000; // ms
* @returns {string} null if url passes all checks, otherwise i18ned error string
*/
async function checkIdentityServerUrl(u: string): Promise<string | null> {
const parsedUrl = url.parse(u);
const parsedUrl = parseUrl(u);
if (parsedUrl.protocol !== "https:") return _t("Identity server URL must be HTTPS");

View file

@ -14,7 +14,6 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import url from "url";
import { ComponentProps } from "react";
import { logger } from "matrix-js-sdk/src/logger";
@ -25,6 +24,7 @@ import Modal from "../Modal";
import SettingsStore from "../settings/SettingsStore";
import IntegrationManager from "../components/views/settings/IntegrationManager";
import { IntegrationManagers } from "./IntegrationManagers";
import { parseUrl } from "../utils/UrlUtils";
export enum Kind {
Account = "account",
@ -42,15 +42,14 @@ export class IntegrationManagerInstance {
) {}
public get name(): string {
const parsed = url.parse(this.uiUrl);
const parsed = parseUrl(this.uiUrl);
return parsed.host ?? "";
}
public get trimmedApiUrl(): string {
const parsed = url.parse(this.apiUrl);
const parsed = parseUrl(this.apiUrl);
parsed.pathname = "";
parsed.path = "";
return url.format(parsed);
return parsed.toString();
}
public getScalarClient(): ScalarAuthClient {

View file

@ -14,7 +14,6 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import url from "url";
import { logger } from "matrix-js-sdk/src/logger";
import { ClientEvent, IClientWellKnown, MatrixClient } from "matrix-js-sdk/src/client";
import { compare } from "matrix-js-sdk/src/utils";
@ -27,6 +26,7 @@ import IntegrationsImpossibleDialog from "../components/views/dialogs/Integratio
import IntegrationsDisabledDialog from "../components/views/dialogs/IntegrationsDisabledDialog";
import WidgetUtils from "../utils/WidgetUtils";
import { MatrixClientPeg } from "../MatrixClientPeg";
import { parseUrl } from "../utils/UrlUtils";
const KIND_PREFERENCE = [
// Ordered: first is most preferred, last is least preferred.
@ -199,7 +199,7 @@ export class IntegrationManagers {
logger.log("Looking up integration manager via .well-known");
if (domainName.startsWith("http:") || domainName.startsWith("https:")) {
// trim off the scheme and just use the domain
domainName = url.parse(domainName).host!;
domainName = parseUrl(domainName).host;
}
let wkConfig: IClientWellKnown;

View file

@ -14,8 +14,6 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import url from "url";
/**
* If a url has no path component, etc. abbreviate it to just the hostname
*
@ -25,11 +23,16 @@ import url from "url";
export function abbreviateUrl(u?: string): string {
if (!u) return "";
const parsedUrl = url.parse(u);
// if it's something we can't parse as a url then just return it
if (!parsedUrl) return u;
let parsedUrl: URL;
try {
parsedUrl = parseUrl(u);
} catch (e) {
console.error(e);
// if it's something we can't parse as a url then just return it
return u;
}
if (parsedUrl.path === "/") {
if (parsedUrl.pathname === "/") {
// we ignore query / hash parts: these aren't relevant for IS server URLs
return parsedUrl.host || "";
}
@ -42,8 +45,15 @@ export function unabbreviateUrl(u?: string): string {
let longUrl = u;
if (!u.startsWith("https://")) longUrl = "https://" + u;
const parsed = url.parse(longUrl);
if (parsed.hostname === null) return u;
const parsed = parseUrl(longUrl);
if (!parsed.hostname) return u;
return longUrl;
}
export function parseUrl(u: string): URL {
if (!u.includes(":")) {
u = window.location.protocol + u;
}
return new URL(u);
}

View file

@ -15,7 +15,6 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import * as url from "url";
import { base32 } from "rfc4648";
import { IWidget, IWidgetData } from "matrix-widget-api";
import { Room } from "matrix-js-sdk/src/models/room";
@ -36,6 +35,7 @@ import { Jitsi } from "../widgets/Jitsi";
import { objectClone } from "./objects";
import { _t } from "../languageHandler";
import { IApp, isAppWidget } from "../stores/WidgetStore";
import { parseUrl } from "./UrlUtils";
// How long we wait for the state event echo to come back from the server
// before waitFor[Room/User]Widget rejects its promise
@ -106,7 +106,7 @@ export default class WidgetUtils {
return false;
}
const testUrl = url.parse(testUrlString);
const testUrl = parseUrl(testUrlString);
let scalarUrls = SdkConfig.get().integrations_widgets_urls;
if (!scalarUrls || scalarUrls.length === 0) {
const defaultManager = IntegrationManagers.sharedInstance().getPrimaryManager();
@ -118,7 +118,7 @@ export default class WidgetUtils {
}
for (let i = 0; i < scalarUrls.length; i++) {
const scalarUrl = url.parse(scalarUrls[i]);
const scalarUrl = parseUrl(scalarUrls[i]);
if (testUrl && scalarUrl) {
if (
testUrl.protocol === scalarUrl.protocol &&