From 4ca99f0e59fa6e10d13ecd36ff11bd7c41dc40cc Mon Sep 17 00:00:00 2001
From: Hugh Nimmo-Smith
Date: Mon, 20 Jan 2025 17:25:46 +0000
Subject: [PATCH] For discussion
---
locales/en/app.json | 8 +-
src/RichError.tsx | 271 ++++++++++++++++++++++++++-------------
src/livekit/openIDSFU.ts | 35 +++--
3 files changed, 209 insertions(+), 105 deletions(-)
diff --git a/locales/en/app.json b/locales/en/app.json
index 7552e4b9..e90b3559 100644
--- a/locales/en/app.json
+++ b/locales/en/app.json
@@ -72,8 +72,12 @@
},
"disconnected_banner": "Connectivity to the server has been lost.",
"error": {
- "auth_connection_failed_details": "<0>The application could not reach the call authentication service at <2>{{url}}2>. If you are the server admin, check the network logs and make sure <5>lk-jwt-service5> is listening at that address.0>",
- "auth_connection_rejected_details": "<0>The application connected to the call authentication service at <2>{{url}}2>, but it responded with status code {{status}} ({{response}}). If you are the server admin, make sure <10>lk-jwt-service10> is listening at that address and check the logs for more information.0>",
+ "configuration_error": "Configuration error",
+ "configuration_error_description": "There is a configuration issues with the system. Please contact your administrator.",
+ "server_error": "Server error",
+ "server_error_description": "There is a server issue with the system. Please try again and contact your administrator if the problem persists.",
+ "network_error": "Network error",
+ "network_error_description": "There is a network issue with the system. Please check your network connection and try again. Alternatively try a different network if available.",
"call_not_found": "Call not found",
"call_not_found_description": "<0>That link doesn't appear to belong to any existing call. Check that you have the right link, or <1>create a new one1>.0>",
"connection_failed": "Connection failed",
diff --git a/src/RichError.tsx b/src/RichError.tsx
index e5b01515..d48e3469 100644
--- a/src/RichError.tsx
+++ b/src/RichError.tsx
@@ -14,10 +14,11 @@ import {
} from "react";
import { Trans, useTranslation } from "react-i18next";
import {
+ ErrorIcon,
OfflineIcon,
PopOutIcon,
} from "@vector-im/compound-design-tokens/assets/web/icons";
-import { Button, Link } from "@vector-im/compound-web";
+import { Button } from "@vector-im/compound-web";
import { ErrorView } from "./ErrorView";
@@ -58,40 +59,22 @@ export class OpenElsewhereError extends RichError {
}
}
-interface AuthConnectionFailedProps {
- livekitServiceUrl: string;
+interface ConfigurationErrorViewProps {
+ children?: ReactNode;
}
-const AuthConnectionFailed: FC = ({
- livekitServiceUrl,
+const ConfigurationErrorView: FC = ({
+ children,
}) => {
const { t } = useTranslation();
const [showDetails, setShowDetails] = useState(false);
const onShowDetailsClick = useCallback(() => setShowDetails(true), []);
return (
-
-
{t("error.connection_failed_description")}
+
+
{t("error.configuration_error_description")}
{showDetails ? (
-
-
- The application could not reach the call authentication service at{" "}
-
- {{ url: livekitServiceUrl } as unknown as ReactElement}
-
- . If you are the server admin, check the network logs and make sure{" "}
-
- lk-jwt-service
- {" "}
- is listening at that address.
-
-
+ children
) : (
+ ,
+ cause,
+ );
+ }
+}
+
+export class ResourceNotFoundConfigurationError extends ConfigurationError {
+ public constructor(url: URL) {
+ super(
+ `The server returned a 404 response for: ${url.href}`,
+
+
+ The request to{" "}
+ {{ url: url.href } as unknown as ReactElement} returned a{" "}
+ 404 response.
+
+ The application received an unexpected response from{" "}
+ {{ url } as unknown as ReactElement}. It received status
+ code {{ status } as unknown as ReactElement}:{" "}
+
{{ response } as unknown as ReactElement}
.
+
+ ,
+ );
+ }
+}
+
+export class FetchError extends ServerError {
+ public constructor(url: URL, cause: unknown) {
+ let message: string;
+ if (cause instanceof Error) {
+ message = cause.message;
+ } else {
+ message = "Unknown error";
+ }
+
+ super(
+ `Failed to connect to ${url.href}: ${message}`,
+
+
+ The application received an unexpected response from{" "}
+ {{ url: url.href } as unknown as ReactElement}. It
+ received status code{" "}
+ {{ message } as unknown as ReactElement}.
+
+ ,
+ );
+ }
+}
+
+export class InvalidServerResponseError extends ServerError {
+ public constructor(url: URL, cause: unknown) {
+ let message: string;
+ if (cause instanceof Error) {
+ message = cause.message;
+ } else {
+ message = "Unknown error";
+ }
+
+ super(
+ `Invalid response received from ${url.href}: ${message}`,
+
+
+ The server at{" "}
+ {{ url: url.href } as unknown as ReactElement} returned
+ an invalid response:{" "}
+
{{ message } as unknown as ReactElement}
+
+ ,
);
}
}
diff --git a/src/livekit/openIDSFU.ts b/src/livekit/openIDSFU.ts
index da6e5777..b88499dc 100644
--- a/src/livekit/openIDSFU.ts
+++ b/src/livekit/openIDSFU.ts
@@ -13,8 +13,11 @@ import { type LivekitFocus } from "matrix-js-sdk/src/matrixrtc/LivekitFocus";
import { useActiveLivekitFocus } from "../room/useActiveFocus";
import {
- AuthConnectionFailedError,
- AuthConnectionRejectedError,
+ FetchError,
+ InvalidServerResponseError,
+ ResourceNotFoundConfigurationError,
+ UnexpectedResponseCodeError,
+ URLBuildingConfigurationError,
} from "../RichError";
export interface SFUConfig {
@@ -87,9 +90,18 @@ async function getLiveKitJWT(
roomName: string,
openIDToken: IOpenIDToken,
): Promise {
+ let url: URL;
+
+ try {
+ // TODO: check that relative URLs are handled as expected by this
+ url = new URL("sfu/get", livekitServiceURL);
+ } catch (e) {
+ throw new URLBuildingConfigurationError(livekitServiceURL, e);
+ }
+
let res: Response;
try {
- res = await fetch(livekitServiceURL + "/sfu/get", {
+ res = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
@@ -101,16 +113,17 @@ async function getLiveKitJWT(
}),
});
} catch (e) {
- throw new AuthConnectionFailedError(livekitServiceURL, e);
+ throw new FetchError(url, e);
}
if (!res.ok) {
throw res.status === 404
- ? new AuthConnectionFailedError(livekitServiceURL)
- : new AuthConnectionRejectedError(
- livekitServiceURL,
- res.status,
- await res.text(),
- );
+ ? new ResourceNotFoundConfigurationError(url)
+ : new UnexpectedResponseCodeError(url, res.status, await res.text());
+ }
+
+ try {
+ return await res.json();
+ } catch (e) {
+ throw new InvalidServerResponseError(url, e);
}
- return await res.json();
}