import 'dart:developer'; import 'dart:io'; import 'dart:convert'; import 'package:dio/adapter.dart'; import 'package:dio/dio.dart'; import 'package:dio/native_imp.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../../app.dart'; import '../../authentication/bloc/authentication_bloc.dart'; import '../../environment/app_config.dart'; import '../../utils/const_enum.dart'; import '../../utils/local_storage.dart'; class DioProvider extends DioForNative { factory DioProvider({ String? baseUrl, String contentType = Headers.jsonContentType, int timeout = 60000, }) { _instance ??= DioProvider._(baseUrl: baseUrl, contentType: contentType, timeout: timeout); return _instance!; } DioProvider._({ String? baseUrl, String contentType = Headers.jsonContentType, int timeout = 60000, }) : super(BaseOptions( baseUrl: baseUrl ?? FlavorConfig.values.baseUrl, contentType: contentType, sendTimeout: timeout, connectTimeout: timeout, receiveTimeout: timeout, )) { (httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (HttpClient client) { client.badCertificateCallback = (X509Certificate cert, String host, int port) => true; return client; }; interceptors ..add(AuthorizationInterceptor()) ..add(HttpLogInterceptor()) ..add(LogoutInterceptor()) ..add(UnauthorizedInterceptor()); } static DioProvider? _instance; } class AuthorizationInterceptor extends InterceptorsWrapper { @override Future onRequest( RequestOptions options, RequestInterceptorHandler handler, ) async { final String? token = await LocalStorage.getString(LocalStorageKey.access_token); if (token != null && options.path != 'token') { options.headers.putIfAbsent('Authorization', () => 'Bearer $token'); } return handler.next(options); } } class HttpLogInterceptor extends InterceptorsWrapper { @override Future onRequest(RequestOptions options, RequestInterceptorHandler handler) async { log('⭐⭐⭐⭐⭐⭐ onRequest: ${options.uri}\n' 'data=${options.data is Map ? json.encode(options.data) : options.data}\n' 'method=${options.method}\n' 'headers=${options.headers}\n' 'queryParameters=${options.queryParameters}'); return handler.next(options); } @override void onResponse(Response response, ResponseInterceptorHandler handler) { log('🍏🍏🍏🍏🍏🍏 onResponse: ${response.requestOptions.uri}\n' 'statusCode=${response.statusCode}\n' 'data=${response.data is Map ? json.encode(response.data) : response.data}'); return handler.next(response); } @override void onError(DioError err, ErrorInterceptorHandler handler) { log('🔥🔥🔥🔥🔥🔥 onError: ${err.response?.requestOptions.uri}\n' 'errorStatusCode=${err.response?.statusCode}\n' 'errorResponseHeaders=${err.response?.headers}\n' 'errorMessage=${err.message}\n' 'errorData=${err.response?.data}'); return handler.next(err); } } class LogoutInterceptor extends InterceptorsWrapper { @override Future onRequest( RequestOptions options, RequestInterceptorHandler handler, ) async { final headers = options.headers; final String? token = await LocalStorage.getString(LocalStorageKey.access_token); if (token == null && headers.containsKey('Authorization')) { headers.remove('Authorization'); } return handler.next(options); } } class UnauthorizedInterceptor extends InterceptorsWrapper { @override Future onError( DioError err, ErrorInterceptorHandler handler, ) async { final checkUnauthorized = err.type == DioErrorType.response && err.response?.statusCode == HttpStatus.unauthorized && err.requestOptions.path != 'token'; if (checkUnauthorized) { LocalStorage.clearUserInfo(); BlocProvider.of(globalNavigator.currentContext!).add( const AuthenticationStatusChanged(AuthenticationStatus.unauthenticated), ); } return handler.next(err); } } // class DioProvider { // static Dio dio = Dio(); // static FlavorValues flavorValues = FlavorConfig.values; // static Dio instance() { // dio.options.baseUrl = flavorValues.baseUrl; // (dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = // (HttpClient client) { // client.badCertificateCallback = // (X509Certificate cert, String host, int port) => true; // return client; // }; // dio.interceptors.add( // InterceptorsWrapper( // onRequest: (options, handler) { // var token = LocalStorage.getString(LocalStorageKey.access_token); // var refreshTokenUrl = // FlavorConfig.values.baseUrl + EndpointUrl.refreshToken; // if (token.isNotEmpty && (options.path != refreshTokenUrl)) { // options.headers['Authorization'] = 'Bearer $token'; // } // options.headers['Content-Type'] = 'application/json'; // options.headers['accept'] = 'application/json'; // options.connectTimeout = 60000; // options.receiveTimeout = 60000; // log('⭐⭐⭐⭐⭐⭐ onRequest: ${options.uri}\n' // 'data=${options.data}\n' // 'method=${options.method}\n' // // 'headers=${options.headers}\n' // 'queryParameters=${options.queryParameters}'); // return handler.next(options); // }, // onResponse: (response, handler) async { // // log('🍏🍏🍏🍏🍏🍏 onResponse: $response'); // return handler.next(response); // }, // onError: (DioError e, handler) async { // log('🔥🔥🔥🔥🔥🔥 onError: $e\n' // 'Response: ${e.response}'); // if (e.response != null) { // await refreshToken(e, handler); // } else { // handler.next(e); // } // }, // ), // ); // return dio; // } // static void logoutAndNavigationToSplashScreen() { // LocalStorage.clearUserInfo(); // BlocProvider.of(globalNavigator.currentContext!).add( // const AuthenticationStatusChanged( // AuthenticationStatus.unauthenticated, // ), // ); // } // static Future refreshToken( // DioError e, ErrorInterceptorHandler handler) async { // try { // var isCancelPreviousRequest = false; // var isRefreshSuccess = false; // if (e.response?.statusCode == 401) { // try { // var url = FlavorConfig.values.baseUrl + EndpointUrl.login; // var refreshToken = // LocalStorage.getString(LocalStorageKey.refresh_token); // var username = LocalStorage.getString(LocalStorageKey.username); // var res = await dio.post(url, data: { // 'token': refreshToken, // 'username': username, // }); // if (res.statusCode == 200) { // var data = ResponseUser.fromJson(res.data); // LocalStorage.saveUserInfo(data, username); // isRefreshSuccess = true; // } else { // logoutAndNavigationToSplashScreen(); // } // } catch (e) { // logoutAndNavigationToSplashScreen(); // } // } else { // handler.next(e); // } // if (isRefreshSuccess) { // var token = LocalStorage.getString(LocalStorageKey.access_token); // e.requestOptions.headers['Authorization'] = 'Bearer $token'; // e.requestOptions.headers['Content-Type'] = 'application/json'; // e.requestOptions.headers['accept'] = 'application/json'; // e.requestOptions.connectTimeout = 60000; // e.requestOptions.receiveTimeout = 60000; // final opts = Options( // method: e.requestOptions.method, // headers: e.requestOptions.headers, // ); // try { // final cloneReq = await dio.request( // e.requestOptions.path, // options: opts, // data: e.requestOptions.data, // queryParameters: e.requestOptions.queryParameters, // ); // return handler.resolve(cloneReq); // } catch (ex) { // print(ex); // if (!isCancelPreviousRequest) { // isCancelPreviousRequest = true; // handler.next(e); // } // } // } // } catch (e) { // print(e); // } // } // }