THATMobile/lib/core/common/custom_interceptor.dart
2026-03-02 16:57:34 +07:00

138 lines
4.5 KiB
Dart

import 'dart:convert';
import 'package:baseproject/core/common/index.dart';
import 'package:baseproject/core/constants/index.dart';
import 'package:baseproject/features/presentation/app/view/app.dart';
import 'package:baseproject/features/route/route_goto.dart';
import 'package:baseproject/features/usecases/index.dart';
import 'package:dio/dio.dart';
import 'package:get_it/get_it.dart';
class CustomInterceptor extends InterceptorsWrapper {
int retryCount = 0;
@override
// ignore: avoid_void_async
void onRequest(RequestOptions options, RequestInterceptorHandler handler) async {
final String token = LocalStoreManager.getString(StorageKey.tokenUser);
if (token.isNotEmpty) options.headers["Authorization"] = "Bearer $token";
final String method = options.method.toLowerCase();
if (method == 'get' || method == 'put') {
// xử lý double request đá .0
// options.queryParameters.forEach((String key, dynamic value) {
// if (value != null && value is double && Utils.getDecimal(value) == 0) {
// options.queryParameters[key] = value.toInt();
// }
// });
}
// Xóa các field null trong query và body
options.queryParameters.removeWhere((String key, dynamic value) => value == null);
final dynamic data = options.data;
if (data is Map<String, dynamic>) {
options.data = _removeNullFields(data);
}
return super.onRequest(options, handler);
}
@override
// ignore: always_specify_types
onResponse(Response response, ResponseInterceptorHandler handler) {
if (response.data.runtimeType.toString().toLowerCase() == "string") {
response.data = json.decode(response.data);
}
try {
if (response.data["result"] != null) {
response.data = response.data["result"];
}
} catch (_) {}
if (retryCount > 0) {
retryCount = 0;
}
return super.onResponse(response, handler);
}
@override
onError(DioError err, ErrorInterceptorHandler handler) async {
if (retryCount < 3) {
await Future.delayed(Duration(milliseconds: retryCount * 500));
if ((err.response?.statusCode == 403 || err.response?.statusCode == 401)) {
retryCount++;
final Dio dio = GetIt.I();
final RequestOptions options = err.requestOptions;
dio.lock();
dio.interceptors.requestLock.lock();
dio.interceptors.responseLock.lock();
// Refresh token
final UserUseCases sessionRepository = GetIt.I();
final bool token = await sessionRepository.tryRefreshToken();
if (!token) {
dio.unlock();
dio.interceptors.requestLock.unlock();
dio.interceptors.responseLock.unlock();
// ignore: use_build_context_synchronously
gotoLogin(navigatorKey.currentState!.context);
} else {
dio.unlock();
dio.interceptors.requestLock.unlock();
dio.interceptors.responseLock.unlock();
options.headers = <String, dynamic>{
"Content-type": "application/json",
"Authorization": "Bearer ${LocalStoreManager.getString(StorageKey.tokenUser)}"
};
try {
final response = await dio.fetch<dynamic>(options);
return handler.resolve(response);
} catch (e) {
return handler.next(err);
}
}
}
}
// final dynamic errorData = err.response?.data;
// && err.response?.statusCode == 400
// if (errorData != null && errorData["responseException"] != null) {
// final dynamic temp = errorData["responseException"]["exceptionMessage"];
// try {
// if (temp != null && temp["error"] != null) {
// err.response?.data = temp["error"];
// } else {
// err.response?.data = temp;
// }
// } catch (e) {
// err.response?.data = temp;
// }
// }
return super.onError(err, handler);
}
Map<String, dynamic> _removeNullFields(Map<String, dynamic> source) {
final Map<String, dynamic> result = <String, dynamic>{};
source.forEach((String key, dynamic value) {
final dynamic cleanedValue = _cleanValue(value);
if (cleanedValue != null) {
result[key] = cleanedValue;
}
});
return result;
}
dynamic _cleanValue(dynamic value) {
if (value is Map<String, dynamic>) {
return _removeNullFields(value);
}
if (value is List) {
final List<dynamic> cleanedList = value.map(_cleanValue).where((dynamic e) => e != null).toList();
return cleanedList;
}
return value;
}
}