Merge pull request #1875 from TheOneWithTheBraid/braid/well-known-cache
feat: cache .well-known data
This commit is contained in:
commit
5f85acb7f0
|
|
@ -25,7 +25,6 @@ import 'dart:typed_data';
|
||||||
import 'package:async/async.dart';
|
import 'package:async/async.dart';
|
||||||
import 'package:collection/collection.dart' show IterableExtension;
|
import 'package:collection/collection.dart' show IterableExtension;
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:http/http.dart';
|
|
||||||
import 'package:mime/mime.dart';
|
import 'package:mime/mime.dart';
|
||||||
import 'package:olm/olm.dart' as olm;
|
import 'package:olm/olm.dart' as olm;
|
||||||
import 'package:random_string/random_string.dart';
|
import 'package:random_string/random_string.dart';
|
||||||
|
|
@ -124,6 +123,24 @@ class Client extends MatrixApi {
|
||||||
/// The timeout until a typing indicator gets removed automatically.
|
/// The timeout until a typing indicator gets removed automatically.
|
||||||
final Duration typingIndicatorTimeout;
|
final Duration typingIndicatorTimeout;
|
||||||
|
|
||||||
|
DiscoveryInformation? _wellKnown;
|
||||||
|
|
||||||
|
/// the cached .well-known file updated using [getWellknown]
|
||||||
|
DiscoveryInformation? get wellKnown => _wellKnown;
|
||||||
|
|
||||||
|
/// The homeserver this client is communicating with.
|
||||||
|
///
|
||||||
|
/// In case the [homeserver]'s host differs from the previous value, the
|
||||||
|
/// [wellKnown] cache will be invalidated.
|
||||||
|
@override
|
||||||
|
set homeserver(Uri? homeserver) {
|
||||||
|
if (homeserver?.host != this.homeserver?.host) {
|
||||||
|
_wellKnown = null;
|
||||||
|
unawaited(database?.storeWellKnown(null));
|
||||||
|
}
|
||||||
|
super.homeserver = homeserver;
|
||||||
|
}
|
||||||
|
|
||||||
Future<MatrixImageFileResizedResponse?> Function(
|
Future<MatrixImageFileResizedResponse?> Function(
|
||||||
MatrixImageFileResizeArguments)? customImageResizer;
|
MatrixImageFileResizeArguments)? customImageResizer;
|
||||||
|
|
||||||
|
|
@ -531,6 +548,27 @@ class Client extends MatrixApi {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets discovery information about the domain. The file may include
|
||||||
|
/// additional keys, which MUST follow the Java package naming convention,
|
||||||
|
/// e.g. `com.example.myapp.property`. This ensures property names are
|
||||||
|
/// suitably namespaced for each application and reduces the risk of
|
||||||
|
/// clashes.
|
||||||
|
///
|
||||||
|
/// Note that this endpoint is not necessarily handled by the homeserver,
|
||||||
|
/// but by another webserver, to be used for discovering the homeserver URL.
|
||||||
|
///
|
||||||
|
/// The result of this call is stored in [wellKnown] for later use at runtime.
|
||||||
|
@override
|
||||||
|
Future<DiscoveryInformation> getWellknown() async {
|
||||||
|
final wellKnown = await super.getWellknown();
|
||||||
|
|
||||||
|
// do not reset the well known here, so super call
|
||||||
|
super.homeserver = wellKnown.mHomeserver.baseUrl.stripTrailingSlash();
|
||||||
|
_wellKnown = wellKnown;
|
||||||
|
await database?.storeWellKnown(wellKnown);
|
||||||
|
return wellKnown;
|
||||||
|
}
|
||||||
|
|
||||||
/// Checks to see if a username is available, and valid, for the server.
|
/// Checks to see if a username is available, and valid, for the server.
|
||||||
/// Returns the fully-qualified Matrix user ID (MXID) that has been registered.
|
/// Returns the fully-qualified Matrix user ID (MXID) that has been registered.
|
||||||
/// You have to call [checkHomeserver] first to set a homeserver.
|
/// You have to call [checkHomeserver] first to set a homeserver.
|
||||||
|
|
@ -1196,7 +1234,7 @@ class Client extends MatrixApi {
|
||||||
path = '_matrix/media/v3/config';
|
path = '_matrix/media/v3/config';
|
||||||
}
|
}
|
||||||
final requestUri = Uri(path: path);
|
final requestUri = Uri(path: path);
|
||||||
final request = Request('GET', baseUri!.resolveUri(requestUri));
|
final request = http.Request('GET', baseUri!.resolveUri(requestUri));
|
||||||
request.headers['authorization'] = 'Bearer ${bearerToken!}';
|
request.headers['authorization'] = 'Bearer ${bearerToken!}';
|
||||||
final response = await httpClient.send(request);
|
final response = await httpClient.send(request);
|
||||||
final responseBody = await response.stream.toBytes();
|
final responseBody = await response.stream.toBytes();
|
||||||
|
|
@ -1236,7 +1274,7 @@ class Client extends MatrixApi {
|
||||||
// removed with msc3916, so just to be explicit
|
// removed with msc3916, so just to be explicit
|
||||||
'allow_remote': allowRemote.toString(),
|
'allow_remote': allowRemote.toString(),
|
||||||
});
|
});
|
||||||
final request = Request('GET', baseUri!.resolveUri(requestUri));
|
final request = http.Request('GET', baseUri!.resolveUri(requestUri));
|
||||||
request.headers['authorization'] = 'Bearer ${bearerToken!}';
|
request.headers['authorization'] = 'Bearer ${bearerToken!}';
|
||||||
final response = await httpClient.send(request);
|
final response = await httpClient.send(request);
|
||||||
final responseBody = await response.stream.toBytes();
|
final responseBody = await response.stream.toBytes();
|
||||||
|
|
@ -1279,7 +1317,7 @@ class Client extends MatrixApi {
|
||||||
// removed with msc3916, so just to be explicit
|
// removed with msc3916, so just to be explicit
|
||||||
'allow_remote': allowRemote.toString(),
|
'allow_remote': allowRemote.toString(),
|
||||||
});
|
});
|
||||||
final request = Request('GET', baseUri!.resolveUri(requestUri));
|
final request = http.Request('GET', baseUri!.resolveUri(requestUri));
|
||||||
request.headers['authorization'] = 'Bearer ${bearerToken!}';
|
request.headers['authorization'] = 'Bearer ${bearerToken!}';
|
||||||
final response = await httpClient.send(request);
|
final response = await httpClient.send(request);
|
||||||
final responseBody = await response.stream.toBytes();
|
final responseBody = await response.stream.toBytes();
|
||||||
|
|
@ -1315,7 +1353,7 @@ class Client extends MatrixApi {
|
||||||
'url': url.toString(),
|
'url': url.toString(),
|
||||||
if (ts != null) 'ts': ts.toString(),
|
if (ts != null) 'ts': ts.toString(),
|
||||||
});
|
});
|
||||||
final request = Request('GET', baseUri!.resolveUri(requestUri));
|
final request = http.Request('GET', baseUri!.resolveUri(requestUri));
|
||||||
request.headers['authorization'] = 'Bearer ${bearerToken!}';
|
request.headers['authorization'] = 'Bearer ${bearerToken!}';
|
||||||
final response = await httpClient.send(request);
|
final response = await httpClient.send(request);
|
||||||
final responseBody = await response.stream.toBytes();
|
final responseBody = await response.stream.toBytes();
|
||||||
|
|
@ -1369,7 +1407,7 @@ class Client extends MatrixApi {
|
||||||
'allow_remote': allowRemote.toString(),
|
'allow_remote': allowRemote.toString(),
|
||||||
});
|
});
|
||||||
|
|
||||||
final request = Request('GET', baseUri!.resolveUri(requestUri));
|
final request = http.Request('GET', baseUri!.resolveUri(requestUri));
|
||||||
request.headers['authorization'] = 'Bearer ${bearerToken!}';
|
request.headers['authorization'] = 'Bearer ${bearerToken!}';
|
||||||
final response = await httpClient.send(request);
|
final response = await httpClient.send(request);
|
||||||
final responseBody = await response.stream.toBytes();
|
final responseBody = await response.stream.toBytes();
|
||||||
|
|
@ -1956,12 +1994,16 @@ class Client extends MatrixApi {
|
||||||
_accountData = data;
|
_accountData = data;
|
||||||
_updatePushrules();
|
_updatePushrules();
|
||||||
});
|
});
|
||||||
|
_discoveryDataLoading = database.getWellKnown().then((data) {
|
||||||
|
_wellKnown = data;
|
||||||
|
});
|
||||||
// ignore: deprecated_member_use_from_same_package
|
// ignore: deprecated_member_use_from_same_package
|
||||||
presences.clear();
|
presences.clear();
|
||||||
if (waitUntilLoadCompletedLoaded) {
|
if (waitUntilLoadCompletedLoaded) {
|
||||||
await userDeviceKeysLoading;
|
await userDeviceKeysLoading;
|
||||||
await roomsLoading;
|
await roomsLoading;
|
||||||
await _accountDataLoading;
|
await _accountDataLoading;
|
||||||
|
await _discoveryDataLoading;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_initLock = false;
|
_initLock = false;
|
||||||
|
|
@ -2784,10 +2826,13 @@ class Client extends MatrixApi {
|
||||||
Future? userDeviceKeysLoading;
|
Future? userDeviceKeysLoading;
|
||||||
Future? roomsLoading;
|
Future? roomsLoading;
|
||||||
Future? _accountDataLoading;
|
Future? _accountDataLoading;
|
||||||
|
Future? _discoveryDataLoading;
|
||||||
Future? firstSyncReceived;
|
Future? firstSyncReceived;
|
||||||
|
|
||||||
Future? get accountDataLoading => _accountDataLoading;
|
Future? get accountDataLoading => _accountDataLoading;
|
||||||
|
|
||||||
|
Future? get wellKnownLoading => _discoveryDataLoading;
|
||||||
|
|
||||||
/// A map of known device keys per user.
|
/// A map of known device keys per user.
|
||||||
Map<String, DeviceKeysList> get userDeviceKeys => _userDeviceKeys;
|
Map<String, DeviceKeysList> get userDeviceKeys => _userDeviceKeys;
|
||||||
Map<String, DeviceKeysList> _userDeviceKeys = {};
|
Map<String, DeviceKeysList> _userDeviceKeys = {};
|
||||||
|
|
@ -3593,6 +3638,7 @@ class SdkError {
|
||||||
|
|
||||||
class SyncConnectionException implements Exception {
|
class SyncConnectionException implements Exception {
|
||||||
final Object originalException;
|
final Object originalException;
|
||||||
|
|
||||||
SyncConnectionException(this.originalException);
|
SyncConnectionException(this.originalException);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,9 @@ import 'package:matrix/src/utils/queued_to_device_event.dart';
|
||||||
|
|
||||||
abstract class DatabaseApi {
|
abstract class DatabaseApi {
|
||||||
int get maxFileSize => 1 * 1024 * 1024;
|
int get maxFileSize => 1 * 1024 * 1024;
|
||||||
|
|
||||||
bool get supportsFileStoring => false;
|
bool get supportsFileStoring => false;
|
||||||
|
|
||||||
Future<Map<String, dynamic>?> getClient(String name);
|
Future<Map<String, dynamic>?> getClient(String name);
|
||||||
|
|
||||||
Future updateClient(
|
Future updateClient(
|
||||||
|
|
@ -334,6 +336,10 @@ abstract class DatabaseApi {
|
||||||
|
|
||||||
Future<CachedPresence?> getPresence(String userId);
|
Future<CachedPresence?> getPresence(String userId);
|
||||||
|
|
||||||
|
Future<void> storeWellKnown(DiscoveryInformation? discoveryInformation);
|
||||||
|
|
||||||
|
Future<DiscoveryInformation?> getWellKnown();
|
||||||
|
|
||||||
/// Deletes the whole database. The database needs to be created again after
|
/// Deletes the whole database. The database needs to be created again after
|
||||||
/// this.
|
/// this.
|
||||||
Future<void> delete();
|
Future<void> delete();
|
||||||
|
|
|
||||||
|
|
@ -1595,6 +1595,25 @@ class HiveCollectionsDatabase extends DatabaseApi {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> storeWellKnown(DiscoveryInformation? discoveryInformation) {
|
||||||
|
if (discoveryInformation == null) {
|
||||||
|
return _clientBox.delete('discovery_information');
|
||||||
|
}
|
||||||
|
return _clientBox.put(
|
||||||
|
'discovery_information',
|
||||||
|
jsonEncode(discoveryInformation.toJson()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<DiscoveryInformation?> getWellKnown() async {
|
||||||
|
final rawDiscoveryInformation =
|
||||||
|
await _clientBox.get('discovery_information');
|
||||||
|
if (rawDiscoveryInformation == null) return null;
|
||||||
|
return DiscoveryInformation.fromJson(jsonDecode(rawDiscoveryInformation));
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> delete() => _collection.deleteFromDisk();
|
Future<void> delete() => _collection.deleteFromDisk();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1401,6 +1401,25 @@ class FamedlySdkHiveDatabase extends DatabaseApi with ZoneTransactionMixin {
|
||||||
throw UnimplementedError();
|
throw UnimplementedError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> storeWellKnown(DiscoveryInformation? discoveryInformation) {
|
||||||
|
if (discoveryInformation == null) {
|
||||||
|
return _clientBox.delete('discovery_information');
|
||||||
|
}
|
||||||
|
return _clientBox.put(
|
||||||
|
'discovery_information',
|
||||||
|
jsonEncode(discoveryInformation.toJson()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<DiscoveryInformation?> getWellKnown() async {
|
||||||
|
final rawDiscoveryInformation =
|
||||||
|
await _clientBox.get('discovery_information');
|
||||||
|
if (rawDiscoveryInformation == null) return null;
|
||||||
|
return DiscoveryInformation.fromJson(jsonDecode(rawDiscoveryInformation));
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> delete() => Hive.deleteFromDisk();
|
Future<void> delete() => Hive.deleteFromDisk();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1623,6 +1623,25 @@ class MatrixSdkDatabase extends DatabaseApi with DatabaseFileStorage {
|
||||||
return CachedPresence.fromJson(copyMap(rawPresence));
|
return CachedPresence.fromJson(copyMap(rawPresence));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> storeWellKnown(DiscoveryInformation? discoveryInformation) {
|
||||||
|
if (discoveryInformation == null) {
|
||||||
|
return _clientBox.delete('discovery_information');
|
||||||
|
}
|
||||||
|
return _clientBox.put(
|
||||||
|
'discovery_information',
|
||||||
|
jsonEncode(discoveryInformation.toJson()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<DiscoveryInformation?> getWellKnown() async {
|
||||||
|
final rawDiscoveryInformation =
|
||||||
|
await _clientBox.get('discovery_information');
|
||||||
|
if (rawDiscoveryInformation == null) return null;
|
||||||
|
return DiscoveryInformation.fromJson(jsonDecode(rawDiscoveryInformation));
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> delete() async {
|
Future<void> delete() async {
|
||||||
// database?.path is null on web
|
// database?.path is null on web
|
||||||
|
|
|
||||||
|
|
@ -175,6 +175,7 @@ void main() {
|
||||||
matrix.userDeviceKeys['@alice:example.com']?.deviceKeys['JLAFKJWSCS']
|
matrix.userDeviceKeys['@alice:example.com']?.deviceKeys['JLAFKJWSCS']
|
||||||
?.verified,
|
?.verified,
|
||||||
false);
|
false);
|
||||||
|
expect(matrix.wellKnown, isNull);
|
||||||
|
|
||||||
await matrix.handleSync(SyncUpdate.fromJson({
|
await matrix.handleSync(SyncUpdate.fromJson({
|
||||||
'next_batch': 'fakesync',
|
'next_batch': 'fakesync',
|
||||||
|
|
@ -1168,6 +1169,13 @@ void main() {
|
||||||
await client.dispose(closeDatabase: true);
|
await client.dispose(closeDatabase: true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('wellKnown cache', () async {
|
||||||
|
final client = await getClient();
|
||||||
|
expect(client.wellKnown, null);
|
||||||
|
await client.getWellknown();
|
||||||
|
expect(client.wellKnown?.mHomeserver.baseUrl.host, 'matrix.example.com');
|
||||||
|
});
|
||||||
|
|
||||||
test('refreshAccessToken', () async {
|
test('refreshAccessToken', () async {
|
||||||
final client = await getClient();
|
final client = await getClient();
|
||||||
expect(client.accessToken, 'abcd');
|
expect(client.accessToken, 'abcd');
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue