From 6868e61d5da66403e951482b14588ffa14197b8b Mon Sep 17 00:00:00 2001 From: "mr.mojtaba" Date: Sun, 29 Jun 2025 11:55:33 +0330 Subject: [PATCH] fix : refresh token Completer in app_interceptor --- .../remote/app_interceptor.dart | 60 +++++++++++-------- 1 file changed, 35 insertions(+), 25 deletions(-) diff --git a/packages/core/lib/infrastructure/remote/app_interceptor.dart b/packages/core/lib/infrastructure/remote/app_interceptor.dart index 77b745b..725889c 100644 --- a/packages/core/lib/infrastructure/remote/app_interceptor.dart +++ b/packages/core/lib/infrastructure/remote/app_interceptor.dart @@ -4,46 +4,56 @@ import '../../core.dart'; typedef RefreshTokenCallback = Future Function(); class AppInterceptor extends Interceptor { final RefreshTokenCallback refreshTokenCallback; + Completer? _refreshCompleter; AppInterceptor({required this.refreshTokenCallback}); + @override Future onError(DioException err, ErrorInterceptorHandler handler) async { if (err.response?.statusCode == 401 && !ApiHandler.isRefreshing) { - ApiHandler.cancelAllRequests("Token expired - refreshing"); - ApiHandler.isRefreshing = true; + if (_refreshCompleter == null) { + _refreshCompleter = Completer(); + ApiHandler.isRefreshing = true; + + try { + final newToken = await refreshTokenCallback(); + if (newToken == null) throw Exception("Refresh failed"); + + ApiHandler.reset(); + _refreshCompleter?.complete(newToken); + } catch (e) { + _refreshCompleter?.completeError(e); + if (!ApiHandler.isRedirecting) { + ApiHandler.isRedirecting = true; + ApiHandler.cancelAllRequests("Cancel All Requests - Unauthorized"); + if (Get.currentRoute != '/Auth') { + Get.offAllNamed('/Auth'); + } + } + } finally { + ApiHandler.isRefreshing = false; + _refreshCompleter = null; + } + } try { - final newToken = await refreshTokenCallback(); - if (newToken == null) throw Exception("Refresh failed"); + final newToken = await _refreshCompleter!.future; + if (newToken != null) { + final opts = err.requestOptions; + opts.headers['Authorization'] = 'Bearer $newToken'; - - ApiHandler.reset(); - - final opts = err.requestOptions; - opts.headers['Authorization'] = 'Bearer $newToken'; - - - final dio = Dio(); - final cloneReq = await dio.fetch(opts); - handler.resolve(cloneReq); - return; - } catch (e) { - if (!ApiHandler.isRedirecting) { - ApiHandler.isRedirecting = true; - ApiHandler.cancelAllRequests("Cancel All Requests - Unauthorized"); - if (Get.currentRoute != '/Auth') { - Get.offAllNamed('/Auth'); - } + final dio = Dio(); + final cloneReq = await dio.fetch(opts); + handler.resolve(cloneReq); + return; } + } catch (_) { handler.reject(err); - } finally { - ApiHandler.isRefreshing = false; } } else if (err.type == DioExceptionType.cancel) { - handler.next(err); } else { handler.next(err);