diff --git a/packages/stream_chat/lib/src/client/client.dart b/packages/stream_chat/lib/src/client/client.dart index 050d36f1..3d314063 100644 --- a/packages/stream_chat/lib/src/client/client.dart +++ b/packages/stream_chat/lib/src/client/client.dart @@ -31,6 +31,7 @@ import 'package:stream_chat/src/event_type.dart'; import 'package:stream_chat/src/location.dart'; import 'package:stream_chat/src/ws/connection_status.dart'; import 'package:stream_chat/src/ws/websocket.dart'; +import 'package:stream_chat/version.dart'; /// Handler function used for logging records. Function requires a single /// [LogRecord] as the only parameter. @@ -80,6 +81,9 @@ class StreamChatClient { location: location, connectTimeout: connectTimeout, receiveTimeout: receiveTimeout, + headers: { + 'X-Stream-Client': userAgent, + }, ); _chatApi = chatApi ?? @@ -99,6 +103,9 @@ class StreamChatClient { tokenManager: _tokenManager, handler: handleEvent, logger: detachedLogger('🔌'), + queryParams: { + 'X-Stream-Client': userAgent, + }, ); _retryPolicy = retryPolicy ?? diff --git a/packages/stream_chat/lib/src/core/http/stream_http_client.dart b/packages/stream_chat/lib/src/core/http/stream_http_client.dart index 406138c3..c5f46144 100644 --- a/packages/stream_chat/lib/src/core/http/stream_http_client.dart +++ b/packages/stream_chat/lib/src/core/http/stream_http_client.dart @@ -33,11 +33,14 @@ class StreamHttpClient { ..options.baseUrl = _options.baseUrl ..options.receiveTimeout = _options.receiveTimeout.inMilliseconds ..options.connectTimeout = _options.connectTimeout.inMilliseconds - ..options.queryParameters = {'api_key': apiKey} + ..options.queryParameters = { + 'api_key': apiKey, + ..._options.queryParams, + } ..options.headers = { 'Content-Type': 'application/json', - 'X-Stream-Client': _options.userAgent, 'Content-Encoding': 'application/gzip', + ..._options.headers, } ..interceptors.addAll([ if (tokenManager != null) AuthInterceptor(this, tokenManager), diff --git a/packages/stream_chat/lib/src/core/http/stream_http_client_options.dart b/packages/stream_chat/lib/src/core/http/stream_http_client_options.dart index faad46a1..a2fe22e8 100644 --- a/packages/stream_chat/lib/src/core/http/stream_http_client_options.dart +++ b/packages/stream_chat/lib/src/core/http/stream_http_client_options.dart @@ -10,6 +10,8 @@ class StreamHttpClientOptions { this.location, this.connectTimeout = const Duration(seconds: 6), this.receiveTimeout = const Duration(seconds: 6), + this.queryParams = const {}, + this.headers = const {}, }) : _baseUrl = baseUrl ?? _defaultBaseURL; final String _baseUrl; @@ -32,8 +34,20 @@ class StreamHttpClientOptions { /// received timeout, default to 6s final Duration receiveTimeout; - /// Get the current user agent - String get userAgent => 'stream-chat-dart-client-' - '${CurrentPlatform.name}-' - '${PACKAGE_VERSION.split('+')[0]}'; + /// Common query parameters. + /// + /// List values use the default [ListFormat.multiCompatible]. + /// + /// The value can be overridden per parameter by adding a [MultiParam] + /// object wrapping the actual List value and the desired format. + final Map queryParams; + + /// Http request headers. + /// The keys of initial headers will be converted to lowercase, + /// for example 'Content-Type' will be converted to 'content-type'. + /// + /// The key of Header Map is case-insensitive + /// eg: content-type and Content-Type are + /// regard as the same key. + final Map headers; } diff --git a/packages/stream_chat/lib/src/ws/websocket.dart b/packages/stream_chat/lib/src/ws/websocket.dart index f9d8a210..ad378b39 100644 --- a/packages/stream_chat/lib/src/ws/websocket.dart +++ b/packages/stream_chat/lib/src/ws/websocket.dart @@ -13,6 +13,7 @@ import 'package:stream_chat/src/core/models/event.dart'; import 'package:stream_chat/src/core/models/user.dart'; import 'package:stream_chat/src/event_type.dart'; import 'package:stream_chat/src/ws/timer_helper.dart'; +import 'package:stream_chat/version.dart'; import 'package:web_socket_channel/web_socket_channel.dart'; import 'package:web_socket_channel/status.dart' as status; @@ -41,11 +42,15 @@ class WebSocket with TimerHelper { this.reconnectionMonitorInterval = 10, this.healthCheckInterval = 20, this.reconnectionMonitorTimeout = 40, + this.queryParams = const {}, }) : _logger = logger; /// final String apiKey; + /// Additional query parameters to be added to the websocket url + final Map queryParams; + /// WS base url final String baseUrl; @@ -156,6 +161,7 @@ class WebSocket with TimerHelper { 'api_key': apiKey, 'authorization': token.rawValue, 'stream-auth-type': token.authType.raw, + ...queryParams, }; final scheme = baseUrl.startsWith('https') ? 'wss' : 'ws'; final host = baseUrl.replaceAll(RegExp(r'(^\w+:|^)\/\/'), ''); diff --git a/packages/stream_chat/lib/version.dart b/packages/stream_chat/lib/version.dart index d09a2ccc..d3314525 100644 --- a/packages/stream_chat/lib/version.dart +++ b/packages/stream_chat/lib/version.dart @@ -1,6 +1,12 @@ import 'package:stream_chat/src/client/client.dart'; +import 'package:stream_chat/src/core/platform_detector/platform_detector.dart'; /// Current package version /// Used in [StreamChatClient] to build the `x-stream-client` header // ignore: constant_identifier_names const PACKAGE_VERSION = '2.0.0'; + +/// Get the current user agent +String get userAgent => 'stream-chat-dart-client-' + '${CurrentPlatform.name}-' + '${PACKAGE_VERSION.split('+')[0]}';