From 89bf63df05dcc6b983e95d840d4c34b98f0d7a61 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Fri, 5 May 2023 17:39:49 +0530 Subject: [PATCH] feat: add support for external interceptors. Signed-off-by: xsahil03x --- .../stream_chat/lib/src/client/client.dart | 2 + .../lib/src/core/api/stream_chat_api.dart | 5 +- .../lib/src/core/http/stream_http_client.dart | 34 ++++--- packages/stream_chat/lib/stream_chat.dart | 2 + .../core/http/stream_http_client_test.dart | 88 +++++++++++++------ 5 files changed, 88 insertions(+), 43 deletions(-) diff --git a/packages/stream_chat/lib/src/client/client.dart b/packages/stream_chat/lib/src/client/client.dart index 72dfe989..7627cf1d 100644 --- a/packages/stream_chat/lib/src/client/client.dart +++ b/packages/stream_chat/lib/src/client/client.dart @@ -73,6 +73,7 @@ class StreamChatClient { WebSocket? ws, AttachmentFileUploaderProvider attachmentFileUploaderProvider = StreamAttachmentFileUploader.new, + Iterable? chatApiInterceptors, }) { logger.info('Initiating new StreamChatClient'); @@ -91,6 +92,7 @@ class StreamChatClient { connectionIdManager: _connectionIdManager, attachmentFileUploaderProvider: attachmentFileUploaderProvider, logger: detachedLogger('🕸️'), + interceptors: chatApiInterceptors, ); _ws = ws ?? diff --git a/packages/stream_chat/lib/src/core/api/stream_chat_api.dart b/packages/stream_chat/lib/src/core/api/stream_chat_api.dart index 7e725204..b6850bac 100644 --- a/packages/stream_chat/lib/src/core/api/stream_chat_api.dart +++ b/packages/stream_chat/lib/src/core/api/stream_chat_api.dart @@ -1,3 +1,4 @@ +import 'package:dio/dio.dart'; import 'package:logging/logging.dart'; import 'package:stream_chat/src/core/api/attachment_file_uploader.dart'; import 'package:stream_chat/src/core/api/call_api.dart'; @@ -14,7 +15,7 @@ import 'package:stream_chat/src/core/http/token_manager.dart'; export 'device_api.dart' show PushProvider; -/// ApiClient that wraps every other specific api +/// Api_client that wraps every other specific api class StreamChatApi { /// Initialize a new stream chat api StreamChatApi( @@ -26,6 +27,7 @@ class StreamChatApi { AttachmentFileUploaderProvider attachmentFileUploaderProvider = StreamAttachmentFileUploader.new, Logger? logger, + Iterable? interceptors, }) : _fileUploaderProvider = attachmentFileUploaderProvider, _client = client ?? StreamHttpClient( @@ -34,6 +36,7 @@ class StreamChatApi { tokenManager: tokenManager, connectionIdManager: connectionIdManager, logger: logger, + interceptors: interceptors, ); final StreamHttpClient _client; 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 4a13fbaf..99e72339 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 @@ -25,6 +25,7 @@ class StreamHttpClient { TokenManager? tokenManager, ConnectionIdManager? connectionIdManager, Logger? logger, + Iterable? interceptors, }) : _options = options ?? const StreamHttpClientOptions(), httpClient = dio ?? Dio() { httpClient @@ -45,20 +46,25 @@ class StreamHttpClient { if (tokenManager != null) AuthInterceptor(this, tokenManager), if (connectionIdManager != null) ConnectionIdInterceptor(connectionIdManager), - if (logger != null && logger.level != Level.OFF) - LoggingInterceptor( - requestHeader: true, - logPrint: (step, message) { - switch (step) { - case InterceptStep.request: - return logger.info(message); - case InterceptStep.response: - return logger.info(message); - case InterceptStep.error: - return logger.severe(message); - } - }, - ), + ...interceptors ?? + [ + // Add a default logging interceptor if no interceptors are + // provided. + if (logger != null && logger.level != Level.OFF) + LoggingInterceptor( + requestHeader: true, + logPrint: (step, message) { + switch (step) { + case InterceptStep.request: + return logger.info(message); + case InterceptStep.response: + return logger.info(message); + case InterceptStep.error: + return logger.severe(message); + } + }, + ), + ], ]); } diff --git a/packages/stream_chat/lib/stream_chat.dart b/packages/stream_chat/lib/stream_chat.dart index f214c852..1e0df28c 100644 --- a/packages/stream_chat/lib/stream_chat.dart +++ b/packages/stream_chat/lib/stream_chat.dart @@ -3,6 +3,7 @@ library stream_chat; export 'package:async/async.dart'; export 'package:dio/src/cancel_token.dart'; export 'package:dio/src/dio_error.dart'; +export 'package:dio/src/dio_mixin.dart' show Interceptor, InterceptorsWrapper; export 'package:dio/src/multipart_file.dart'; export 'package:dio/src/options.dart'; export 'package:dio/src/options.dart' show ProgressCallback; @@ -19,6 +20,7 @@ export 'src/core/api/responses.dart'; export 'src/core/api/stream_chat_api.dart' show PushProvider; export 'src/core/api/stream_chat_api.dart'; export 'src/core/error/error.dart'; +export 'src/core/http/interceptor/logging_interceptor.dart'; export 'src/core/models/action.dart'; export 'src/core/models/attachment.dart'; export 'src/core/models/attachment_file.dart'; diff --git a/packages/stream_chat/test/src/core/http/stream_http_client_test.dart b/packages/stream_chat/test/src/core/http/stream_http_client_test.dart index 4854b98f..51533b11 100644 --- a/packages/stream_chat/test/src/core/http/stream_http_client_test.dart +++ b/packages/stream_chat/test/src/core/http/stream_http_client_test.dart @@ -86,41 +86,73 @@ void main() { }, ); - test('loggingInterceptor should be added if logger is provided', () { - const apiKey = 'api-key'; - final client = StreamHttpClient( - apiKey, - logger: Logger('test-logger'), - ); + group('loggingInterceptor', () { + test('should be added if logger is provided', () { + const apiKey = 'api-key'; + final client = StreamHttpClient( + apiKey, + logger: Logger('test-logger'), + ); - expect( - client.httpClient.interceptors.whereType().length, - 1, - ); - }); + expect( + client.httpClient.interceptors.whereType().length, + 1, + ); + }); - test('loggingInterceptor should log requests', () async { - const apiKey = 'api-key'; - final logger = MockLogger(); - final client = StreamHttpClient(apiKey, logger: logger); + test('should not be added if logger.level is OFF', () { + const apiKey = 'api-key'; + final client = StreamHttpClient( + apiKey, + logger: Logger.detached('test-logger')..level = Level.OFF, + ); - try { - await client.get('path'); - } catch (_) {} + expect( + client.httpClient.interceptors.whereType().length, + 0, + ); + }); - verify(() => logger.info(any())).called(greaterThan(0)); - }); + test('should not be added if `interceptors` are provided', () { + const apiKey = 'api-key'; + final client = StreamHttpClient( + apiKey, + logger: Logger.detached('test-logger'), + interceptors: [ + // Sample Interceptor. + InterceptorsWrapper(), + ], + ); - test('loggingInterceptor should log error', () async { - const apiKey = 'api-key'; - final logger = MockLogger(); - final client = StreamHttpClient(apiKey, logger: logger); + expect( + client.httpClient.interceptors.whereType().length, + 0, + ); + }); - try { - await client.get('path'); - } catch (_) {} + test('should log requests', () async { + const apiKey = 'api-key'; + final logger = MockLogger(); + final client = StreamHttpClient(apiKey, logger: logger); - verify(() => logger.severe(any())).called(greaterThan(0)); + try { + await client.get('path'); + } catch (_) {} + + verify(() => logger.info(any())).called(greaterThan(0)); + }); + + test('should log error', () async { + const apiKey = 'api-key'; + final logger = MockLogger(); + final client = StreamHttpClient(apiKey, logger: logger); + + try { + await client.get('path'); + } catch (_) {} + + verify(() => logger.severe(any())).called(greaterThan(0)); + }); }); test('`.close` should close the dio client', () async {