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) { 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 = { "Content-type": "application/json", "Authorization": "Bearer ${LocalStoreManager.getString(StorageKey.tokenUser)}" }; try { final response = await dio.fetch(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 _removeNullFields(Map source) { final Map result = {}; 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) { return _removeNullFields(value); } if (value is List) { final List cleanedList = value.map(_cleanValue).where((dynamic e) => e != null).toList(); return cleanedList; } return value; } }