TF-3493 Ensures that a URI always uses wss:// or ws://, helping avoid the error Unsupported URL scheme 'https'

Signed-off-by: dab246 <tdvu@linagora.com>
This commit is contained in:
dab246
2025-02-21 11:37:54 +07:00
committed by Dat H. Pham
parent 83ec6016af
commit 535a862777
3 changed files with 43 additions and 2 deletions
@@ -30,4 +30,11 @@ extension URIExtension on Uri {
return false;
}
}
Uri ensureWebSocketUri() {
if (scheme == 'ws' || scheme == 'wss') {
return this;
}
return replace(scheme: 'wss');
}
}
@@ -3,7 +3,6 @@ import 'package:core/presentation/extensions/uri_extension.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
group('method convertToQualifiedUrl test', () {
test('convertToQualifiedUrl() should return qualified url when baseUrl is `https://domain.com` and sourceUrl is `https://domain.com/jmap`', () async {
@@ -116,4 +115,36 @@ void main() {
expect(qualifiedUrlResult, equals(qualifiedUrlExpected));
});
});
group('URIExtension.ensureWebSocketUri', () {
test('Should keep ws scheme unchanged', () {
final uri = Uri.parse('ws://example.com/socket');
expect(uri.ensureWebSocketUri().toString(), 'ws://example.com/socket');
});
test('Should keep wss scheme unchanged', () {
final uri = Uri.parse('wss://example.com/socket');
expect(uri.ensureWebSocketUri().toString(), 'wss://example.com/socket');
});
test('Should convert http to wss', () {
final uri = Uri.parse('http://example.com/socket');
expect(uri.ensureWebSocketUri().toString(), 'wss://example.com/socket');
});
test('Should convert https to wss', () {
final uri = Uri.parse('https://example.com/socket');
expect(uri.ensureWebSocketUri().toString(), 'wss://example.com/socket');
});
test('Should keep path and query parameters unchanged', () {
final uri = Uri.parse('http://example.com/socket?token=123');
expect(uri.ensureWebSocketUri().toString(), 'wss://example.com/socket?token=123');
});
test('Should handle URIs without a scheme (default to wss)', () {
final uri = Uri.parse('//example.com/socket');
expect(uri.ensureWebSocketUri().toString(), 'wss://example.com/socket');
});
});
}
@@ -1,6 +1,8 @@
import 'dart:async';
import 'package:core/presentation/extensions/uri_extension.dart';
import 'package:core/utils/app_logger.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/capability/capability_identifier.dart';
import 'package:jmap_dart_client/jmap/core/capability/websocket_capability.dart';
@@ -26,7 +28,7 @@ class WebSocketDatasourceImpl implements WebSocketDatasource {
final webSocketTicket = await _webSocketApi.getWebSocketTicket(session, accountId);
final webSocketUri = _getWebSocketUri(session, accountId);
final webSocketChannel = WebSocketChannel.connect(
Uri.parse('$webSocketUri?ticket=$webSocketTicket'),
Uri.parse('${webSocketUri.ensureWebSocketUri().toString()}?ticket=$webSocketTicket'),
protocols: ["jmap"],
);
@@ -54,6 +56,7 @@ class WebSocketDatasourceImpl implements WebSocketDatasource {
if (webSocketCapability?.supportsPush != true) {
throw WebSocketPushNotSupportedException();
}
log('WebSocketDatasourceImpl::_getWebSocketUri: webSocketCapability = ${webSocketCapability?.toJson()}');
final webSocketUri = webSocketCapability?.url;
if (webSocketUri == null) throw WebSocketUriUnavailableException();