MSC3575 (Sliding Sync) add well-known proxy support (#12307)
* Initial commit Signed-off-by: Ed Geraghty <ed@geraghty.family> * Remove commented code Signed-off-by: Ed Geraghty <ed@geraghty.family> * Change function to reflect it's proxy not native support Signed-off-by: Ed Geraghty <ed@geraghty.family> * Re-add check for servers with native support Signed-off-by: Ed Geraghty <ed@geraghty.family> * Add native support check back in Signed-off-by: Ed Geraghty <ed@geraghty.family> * Re-add endpoint health check function Signed-off-by: Ed Geraghty <ed@geraghty.family> * Use inbuilt `getWellKnown` function Signed-off-by: Ed Geraghty <ed@geraghty.family> * Change the error message to the correct function Signed-off-by: Ed Geraghty <ed@geraghty.family> * Stop storing the proxyurl in the settings for now Signed-off-by: Ed Geraghty <ed@geraghty.family> * Make the logger messages more useful Signed-off-by: Ed Geraghty <ed@geraghty.family> * Start moving the checking logic directly into the controller Signed-off-by: Ed Geraghty <ed@geraghty.family> * Add missing import Signed-off-by: Ed Geraghty <ed@geraghty.family> * Get the client rather than passing it in to the functions Signed-off-by: Ed Geraghty <ed@geraghty.family> * remove invalid `function` keyword Signed-off-by: Ed Geraghty <ed@geraghty.family> * Fix imports Signed-off-by: Ed Geraghty <ed@geraghty.family> * Our new functions are private We shouldn't(?) have to use these check in future elsewhere Signed-off-by: Ed Geraghty <ed@geraghty.family> * Change our proxy check function to return a boolean Signed-off-by: Ed Geraghty <ed@geraghty.family> * Make `nativeSlidingSyncSupport` also return boolean, add in health check Signed-off-by: Ed Geraghty <ed@geraghty.family> * Disable the sliding sync option if the server doesn't support Signed-off-by: Ed Geraghty <ed@geraghty.family> * Only enable the setting if it passes (again) Signed-off-by: Ed Geraghty <ed@geraghty.family> * Update our comments to better match what's going on Signed-off-by: Ed Geraghty <ed@geraghty.family> * Remove unused dialog Signed-off-by: Ed Geraghty <ed@geraghty.family> * Add a well-known check on start-up, if sliding sync has been enabled Signed-off-by: Ed Geraghty <ed@geraghty.family> * Check against the correct endpoint... Signed-off-by: Ed Geraghty <ed@geraghty.family> * Extract baseUrl as we'll reuse it Signed-off-by: Ed Geraghty <ed@geraghty.family> * Make the logs differentiate between the types of proxy Signed-off-by: Ed Geraghty <ed@geraghty.family> * Grab the client well-known directly for use Can't use the client object at this point, it hasn't read in the well-known Signed-off-by: Ed Geraghty <ed@geraghty.family> * Add myself to the copyright assignation I wrote the majority of this file... Signed-off-by: Ed Geraghty <ed@geraghty.family> * Only return `true` if it's actually there Signed-off-by: Ed Geraghty <ed@geraghty.family> * Correct the `proxySlidingSyncSupport` function comment to match the code Signed-off-by: Ed Geraghty <ed@geraghty.family> * Correct the `nativeSlidingSyncSupport`function comment to match the code Signed-off-by: Ed Geraghty <ed@geraghty.family> * Another comment/functionality paring Signed-off-by: Ed Geraghty <ed@geraghty.family> * Remove duplicated types from the doc Signed-off-by: Ed Geraghty <ed@geraghty.family> * Move await to the previous line Removes brackets, and corrects `wellKnown` from being a `Promise` Signed-off-by: Ed Geraghty <ed@geraghty.family> * use `waitForClientWellKnown` to avoid a race condition with the request Signed-off-by: Ed Geraghty <ed@geraghty.family> * Move getting the client out of the `if`, use `waitForClientWellKnown` Signed-off-by: Ed Geraghty <ed@geraghty.family> * Remove `beforeChange` override Signed-off-by: Ed Geraghty <ed@geraghty.family> * Move proxy setup logic into `SlidingSyncManager` Signed-off-by: Ed Geraghty <ed@geraghty.family> * Swap `configure` to private, we call it from `setup` which handles proxy Signed-off-by: Ed Geraghty <ed@geraghty.family> * Promises are always `true` TIL. Signed-off-by: Ed Geraghty <ed@geraghty.family> * use `timeoutSignal` Signed-off-by: Ed Geraghty <ed@geraghty.family> * Change message when there's no server support Signed-off-by: Ed Geraghty <ed@geraghty.family> * Refactor `slidingSyncHealthCheck` Signed-off-by: Ed Geraghty <ed@geraghty.family> * Refactor `nativeSlidingSyncSupport` with try/catch Signed-off-by: Ed Geraghty <ed@geraghty.family> * Change comment to hotlink Signed-off-by: Ed Geraghty <ed@geraghty.family> * Try and make the toggle disabled when there's no endpoint Signed-off-by: Ed Geraghty <ed@geraghty.family> * Move the if statement outside the refactored fn to avoid an await Signed-off-by: Ed Geraghty <ed@geraghty.family> * Revert "Swap `configure` to private, we call it from `setup` which handles proxy" This reverts commit c80a00b50c261becc9ad58e08d2a893d572d8426. * Remove unused import Signed-off-by: Ed Geraghty <ed@geraghty.family> * Further refactor `slidingSyncHealthCheck` `proxySlidingSyncSupport` already checks the client well-known is there Signed-off-by: Ed Geraghty <ed@geraghty.family> * Make `proxySlidingSyncSupport` log on success Signed-off-by: Ed Geraghty <ed@geraghty.family> * Clarify log message for proxy being up Signed-off-by: Ed Geraghty <ed@geraghty.family> * Move the logic into SlidingSyncManager All so we can set a static variable because the disabled check isn't asynchronous :) Signed-off-by: Ed Geraghty <ed@geraghty.family> * Obviously this isn't a return so don't overwrite with false! Signed-off-by: Ed Geraghty <ed@geraghty.family> * Remove outdated comment Signed-off-by: Ed Geraghty <ed@geraghty.family> * No need to pass in the client Signed-off-by: Ed Geraghty <ed@geraghty.family> * Activating SS should probably be info level logs Signed-off-by: Ed Geraghty <ed@geraghty.family> * If we've not enabled sliding sync, push the logs down a bit Signed-off-by: Ed Geraghty <ed@geraghty.family> * Update i18n error message Signed-off-by: Ed Geraghty <ed@geraghty.family> * Remove unused i18n strings Signed-off-by: Ed Geraghty <ed@geraghty.family> * Correct log message Signed-off-by: Ed Geraghty <ed@geraghty.family> * Prettier Signed-off-by: Ed Geraghty <ed@geraghty.family> * Remove many of the log messages Signed-off-by: Ed Geraghty <ed@geraghty.family> * Short out of `checkSupport` if it's `true` Signed-off-by: Ed Geraghty <ed@geraghty.family> * Add the endpoint back into the log when we're enabling it Signed-off-by: Ed Geraghty <ed@geraghty.family> * Note in the comment that `feature_sliding_sync_proxy_url` is legacy Signed-off-by: Ed Geraghty <ed@geraghty.family> * Expand the well-known liveness check log Signed-off-by: Ed Geraghty <ed@geraghty.family> * No need to stall the client waiting for sliding sync support * `AutoDiscovery.findClientConfig` throws if the baseUrl is blank * Fix `getProxyFromWellKnown` (?) * Add missing semicolon Sorry, linter! Signed-off-by: Ed Geraghty <ed@geraghty.family> * Pass our `MatrixClient` through instead of trying to grab it Signed-off-by: Ed Geraghty <ed@geraghty.family> * Add missing return in function comment Signed-off-by: Ed Geraghty <ed@geraghty.family> * Actually pass through our Client, not the Peg object Signed-off-by: Ed Geraghty <ed@geraghty.family> * Remove SonarCube smell complaint Signed-off-by: Ed Geraghty <ed@geraghty.family> * Neew to make our other two methods public to test Signed-off-by: Ed Geraghty <ed@geraghty.family> * First passing test Hurrah! Signed-off-by: Ed Geraghty <ed@geraghty.family> * Two more tests, this time on `checkSupport` Signed-off-by: Ed Geraghty <ed@geraghty.family> * Reset our `serverSupportsSlidingSync` between tests Signed-off-by: Ed Geraghty <ed@geraghty.family> * Check the static member is being set Signed-off-by: Ed Geraghty <ed@geraghty.family> * Move the static assignation down to the relevant tests Signed-off-by: Ed Geraghty <ed@geraghty.family> * Pull getProxyFromWellKnown mocking up Signed-off-by: Ed Geraghty <ed@geraghty.family> * Check we /haven't/ shorted out Signed-off-by: Ed Geraghty <ed@geraghty.family> * Move our spy up so we can reuse it Signed-off-by: Ed Geraghty <ed@geraghty.family> * Check spidering is being called Signed-off-by: Ed Geraghty <ed@geraghty.family> * Test the proxy is declared Signed-off-by: Ed Geraghty <ed@geraghty.family> * Test entered manually Signed-off-by: Ed Geraghty <ed@geraghty.family> * Sorry, linter * I guess these strings are wrong? * Replace any with string Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Ed Geraghty <ed@geraghty.family> Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
parent
641a20ce63
commit
bb4f57583f
7 changed files with 154 additions and 171 deletions
|
@ -1,142 +0,0 @@
|
|||
/*
|
||||
Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import { MatrixClient, Method } from "matrix-js-sdk/src/matrix";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
|
||||
import { _t } from "../../../languageHandler";
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
import TextInputDialog from "./TextInputDialog";
|
||||
import withValidation from "../elements/Validation";
|
||||
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
||||
import { useAsyncMemo } from "../../../hooks/useAsyncMemo";
|
||||
import { SettingLevel } from "../../../settings/SettingLevel";
|
||||
|
||||
/**
|
||||
* Check that the server natively supports sliding sync.
|
||||
* @param cli The MatrixClient of the logged in user.
|
||||
* @throws if the proxy server is unreachable or not configured to the given homeserver
|
||||
*/
|
||||
async function syncHealthCheck(cli: MatrixClient): Promise<void> {
|
||||
await cli.http.authedRequest(Method.Post, "/sync", undefined, undefined, {
|
||||
localTimeoutMs: 10 * 1000, // 10s
|
||||
prefix: "/_matrix/client/unstable/org.matrix.msc3575",
|
||||
});
|
||||
logger.info("server natively support sliding sync OK");
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the proxy url is in fact a sliding sync proxy endpoint and it is up.
|
||||
* @param endpoint The proxy endpoint url
|
||||
* @param hsUrl The homeserver url of the logged in user.
|
||||
* @throws if the proxy server is unreachable or not configured to the given homeserver
|
||||
*/
|
||||
async function proxyHealthCheck(endpoint: string, hsUrl?: string): Promise<void> {
|
||||
const controller = new AbortController();
|
||||
const id = window.setTimeout(() => controller.abort(), 10 * 1000); // 10s
|
||||
const res = await fetch(endpoint + "/client/server.json", {
|
||||
signal: controller.signal,
|
||||
});
|
||||
clearTimeout(id);
|
||||
if (res.status != 200) {
|
||||
throw new Error(`proxyHealthCheck: proxy server returned HTTP ${res.status}`);
|
||||
}
|
||||
const body = await res.json();
|
||||
if (body.server !== hsUrl) {
|
||||
throw new Error(`proxyHealthCheck: client using ${hsUrl} but server is as ${body.server}`);
|
||||
}
|
||||
logger.info("sliding sync proxy is OK");
|
||||
}
|
||||
|
||||
export const SlidingSyncOptionsDialog: React.FC<{ onFinished(enabled: boolean): void }> = ({ onFinished }) => {
|
||||
const cli = MatrixClientPeg.safeGet();
|
||||
const currentProxy = SettingsStore.getValue("feature_sliding_sync_proxy_url");
|
||||
const hasNativeSupport = useAsyncMemo(
|
||||
() =>
|
||||
syncHealthCheck(cli).then(
|
||||
() => true,
|
||||
() => false,
|
||||
),
|
||||
[],
|
||||
null,
|
||||
);
|
||||
|
||||
let nativeSupport: string;
|
||||
if (hasNativeSupport === null) {
|
||||
nativeSupport = _t("labs|sliding_sync_checking");
|
||||
} else {
|
||||
nativeSupport = hasNativeSupport
|
||||
? _t("labs|sliding_sync_server_support")
|
||||
: _t("labs|sliding_sync_server_no_support");
|
||||
}
|
||||
|
||||
const validProxy = withValidation<undefined, { error?: unknown }>({
|
||||
async deriveData({ value }): Promise<{ error?: unknown }> {
|
||||
if (!value) return {};
|
||||
try {
|
||||
await proxyHealthCheck(value, MatrixClientPeg.safeGet().baseUrl);
|
||||
return {};
|
||||
} catch (error) {
|
||||
return { error };
|
||||
}
|
||||
},
|
||||
rules: [
|
||||
{
|
||||
key: "required",
|
||||
test: async ({ value }) => !!value || !!hasNativeSupport,
|
||||
invalid: () => _t("labs|sliding_sync_server_specify_proxy"),
|
||||
},
|
||||
{
|
||||
key: "working",
|
||||
final: true,
|
||||
test: async (_, { error }) => !error,
|
||||
valid: () => _t("spotlight|public_rooms|network_dropdown_available_valid"),
|
||||
invalid: ({ error }) => (error instanceof Error ? error.message : null),
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
return (
|
||||
<TextInputDialog
|
||||
title={_t("labs|sliding_sync_configuration")}
|
||||
description={
|
||||
<div>
|
||||
<div>
|
||||
<b>{_t("labs|sliding_sync_disable_warning")}</b>
|
||||
</div>
|
||||
{nativeSupport}
|
||||
</div>
|
||||
}
|
||||
placeholder={
|
||||
hasNativeSupport
|
||||
? _t("labs|sliding_sync_proxy_url_optional_label")
|
||||
: _t("labs|sliding_sync_proxy_url_label")
|
||||
}
|
||||
value={currentProxy}
|
||||
button={_t("action|enable")}
|
||||
validator={validProxy}
|
||||
onFinished={(enable, proxyUrl) => {
|
||||
if (enable) {
|
||||
SettingsStore.setValue("feature_sliding_sync_proxy_url", null, SettingLevel.DEVICE, proxyUrl);
|
||||
onFinished(true);
|
||||
} else {
|
||||
onFinished(false);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue