fix : add cancel Token

This commit is contained in:
2025-06-23 10:42:29 +03:30
parent ec0e344e47
commit 1e3614ed58
10 changed files with 140 additions and 88 deletions

View File

@@ -0,0 +1,14 @@
// local
export 'local/hive_local_storage.dart';
export 'local/i_local_storage.dart';
//remote
export 'remote/interfaces/i_form_data.dart';
export 'remote/interfaces/i_http_client.dart';
export 'remote/interfaces/i_http_response.dart';
export 'remote/interfaces/i_remote.dart';
export 'remote/app_interceptor.dart';
export 'remote/dio_form_data.dart';
export 'remote/dio_remote.dart';
export 'remote/dio_response.dart';

View File

@@ -0,0 +1,51 @@
import 'dart:async';
import '../../core.dart';
typedef RefreshTokenCallback = Future<String?> Function();
class AppInterceptor extends Interceptor {
final RefreshTokenCallback refreshTokenCallback;
AppInterceptor({required this.refreshTokenCallback});
@override
Future<void> onError(DioException err, ErrorInterceptorHandler handler) async {
if (err.response?.statusCode == 401 && !ApiHandler.isRefreshing) {
// اول بقیه درخواست‌ها رو کنسل کن
ApiHandler.cancelAllRequests("Token expired - refreshing");
ApiHandler.isRefreshing = true;
try {
final newToken = await refreshTokenCallback();
if (newToken == null) throw Exception("Refresh failed");
// تولید CancelToken جدید برای درخواست‌های بعدی
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");
// TODO: Navigate to login
Get.offAllNamed('/login');
}
handler.reject(err);
} finally {
ApiHandler.isRefreshing = false;
}
} else if (err.type == DioExceptionType.cancel) {
handler.next(err);
} else {
handler.next(err);
}
}
}

View File

@@ -1,18 +1,18 @@
import 'package:flutter/foundation.dart';
import 'package:rasadyar_core/core.dart';
import 'package:rasadyar_core/infrastructure/remote/interfaces/i_form_data.dart';
import 'interfaces/i_http_client.dart';
class DioRemote implements IHttpClient {
String? baseUrl;
late final Dio _dio;
final List<Interceptor> interceptors;
DioRemote({this.baseUrl});
DioRemote({this.baseUrl, this.interceptors = const []});
@override
Future<void> init() async {
final dio = Dio(BaseOptions(baseUrl: baseUrl ?? ''));
dio.interceptors.addAll(interceptors);
if (kDebugMode) {
dio.interceptors.add(
PrettyDioLogger(
@@ -39,6 +39,7 @@ class DioRemote implements IHttpClient {
queryParameters: queryParameters,
options: Options(headers: headers),
onReceiveProgress: onReceiveProgress,
cancelToken: ApiHandler.globalCancelToken
);
if (fromJsonList != null && response.data is List) {
response.data = fromJsonList(response.data);
@@ -68,6 +69,7 @@ class DioRemote implements IHttpClient {
options: Options(headers: headers),
onSendProgress: onSendProgress,
onReceiveProgress: onReceiveProgress,
cancelToken: ApiHandler.globalCancelToken
);
if (fromJson != null) {
@@ -98,6 +100,7 @@ class DioRemote implements IHttpClient {
options: Options(headers: headers),
onSendProgress: onSendProgress,
onReceiveProgress: onReceiveProgress,
cancelToken: ApiHandler.globalCancelToken
);
return DioResponse<T>(response);
}
@@ -114,6 +117,7 @@ class DioRemote implements IHttpClient {
data: data,
queryParameters: queryParameters,
options: Options(headers: headers),
cancelToken: ApiHandler.globalCancelToken
);
return DioResponse<T>(response);
}
@@ -127,6 +131,7 @@ class DioRemote implements IHttpClient {
url,
options: Options(responseType: ResponseType.bytes),
onReceiveProgress: onReceiveProgress,
cancelToken: ApiHandler.globalCancelToken
);
return DioResponse(response);
}
@@ -143,6 +148,7 @@ class DioRemote implements IHttpClient {
data: (formData as DioFormData).raw,
options: Options(headers: headers, contentType: 'multipart/form-data'),
onSendProgress: onSendProgress,
cancelToken: ApiHandler.globalCancelToken
);
return DioResponse<T>(response);
}