fix : refresh token Completer in app_interceptor

This commit is contained in:
2025-06-29 11:55:33 +03:30
parent 1e0eeac1f0
commit 6868e61d5d

View File

@@ -4,33 +4,28 @@ import '../../core.dart';
typedef RefreshTokenCallback = Future<String?> Function(); typedef RefreshTokenCallback = Future<String?> Function();
class AppInterceptor extends Interceptor { class AppInterceptor extends Interceptor {
final RefreshTokenCallback refreshTokenCallback; final RefreshTokenCallback refreshTokenCallback;
Completer<String?>? _refreshCompleter;
AppInterceptor({required this.refreshTokenCallback}); AppInterceptor({required this.refreshTokenCallback});
@override @override
Future<void> onError(DioException err, ErrorInterceptorHandler handler) async { Future<void> onError(DioException err, ErrorInterceptorHandler handler) async {
if (err.response?.statusCode == 401 && !ApiHandler.isRefreshing) { if (err.response?.statusCode == 401 && !ApiHandler.isRefreshing) {
ApiHandler.cancelAllRequests("Token expired - refreshing"); ApiHandler.cancelAllRequests("Token expired - refreshing");
if (_refreshCompleter == null) {
_refreshCompleter = Completer<String?>();
ApiHandler.isRefreshing = true; ApiHandler.isRefreshing = true;
try { try {
final newToken = await refreshTokenCallback(); final newToken = await refreshTokenCallback();
if (newToken == null) throw Exception("Refresh failed"); if (newToken == null) throw Exception("Refresh failed");
ApiHandler.reset(); ApiHandler.reset();
_refreshCompleter?.complete(newToken);
final opts = err.requestOptions;
opts.headers['Authorization'] = 'Bearer $newToken';
final dio = Dio();
final cloneReq = await dio.fetch(opts);
handler.resolve(cloneReq);
return;
} catch (e) { } catch (e) {
_refreshCompleter?.completeError(e);
if (!ApiHandler.isRedirecting) { if (!ApiHandler.isRedirecting) {
ApiHandler.isRedirecting = true; ApiHandler.isRedirecting = true;
ApiHandler.cancelAllRequests("Cancel All Requests - Unauthorized"); ApiHandler.cancelAllRequests("Cancel All Requests - Unauthorized");
@@ -38,12 +33,27 @@ class AppInterceptor extends Interceptor {
Get.offAllNamed('/Auth'); Get.offAllNamed('/Auth');
} }
} }
handler.reject(err);
} finally { } finally {
ApiHandler.isRefreshing = false; ApiHandler.isRefreshing = false;
_refreshCompleter = null;
}
}
try {
final newToken = await _refreshCompleter!.future;
if (newToken != null) {
final opts = err.requestOptions;
opts.headers['Authorization'] = 'Bearer $newToken';
final dio = Dio();
final cloneReq = await dio.fetch(opts);
handler.resolve(cloneReq);
return;
}
} catch (_) {
handler.reject(err);
} }
} else if (err.type == DioExceptionType.cancel) { } else if (err.type == DioExceptionType.cancel) {
handler.next(err); handler.next(err);
} else { } else {
handler.next(err); handler.next(err);