You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

288 lines
10KB

  1. import 'dart:developer';
  2. import 'dart:io';
  3. import 'dart:convert';
  4. import 'package:dio/adapter.dart';
  5. import 'package:dio/dio.dart';
  6. import 'package:dio/native_imp.dart';
  7. import 'package:farm_tpf/data/repository/user_repository.dart';
  8. import 'package:flutter_bloc/flutter_bloc.dart';
  9. import 'package:get/get.dart' as getx;
  10. import '../../app.dart';
  11. import '../../authentication/bloc/authentication_bloc.dart';
  12. import '../../environment/app_config.dart';
  13. import '../../presentation/screens/login/login_page.dart';
  14. import '../../routes/routes.dart';
  15. import '../../utils/const_enum.dart';
  16. import '../../utils/local_storage.dart';
  17. import '../../utils/pref.dart';
  18. class DioProvider extends DioForNative {
  19. factory DioProvider({
  20. String? baseUrl,
  21. String contentType = Headers.jsonContentType,
  22. int timeout = 60000,
  23. }) {
  24. _instance ??= DioProvider._(baseUrl: baseUrl, contentType: contentType, timeout: timeout);
  25. return _instance!;
  26. }
  27. DioProvider._({
  28. String? baseUrl,
  29. String contentType = Headers.jsonContentType,
  30. int timeout = 60000,
  31. }) : super(BaseOptions(
  32. baseUrl: baseUrl ?? FlavorConfig.values.baseUrl,
  33. contentType: contentType,
  34. sendTimeout: timeout,
  35. connectTimeout: timeout,
  36. receiveTimeout: timeout,
  37. )) {
  38. (httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (HttpClient client) {
  39. client.badCertificateCallback = (X509Certificate cert, String host, int port) => true;
  40. return client;
  41. };
  42. interceptors
  43. ..add(AuthorizationInterceptor())
  44. ..add(HttpLogInterceptor())
  45. ..add(LogoutInterceptor())
  46. ..add(UnauthorizedInterceptor());
  47. }
  48. static DioProvider? _instance;
  49. }
  50. class AuthorizationInterceptor extends InterceptorsWrapper {
  51. @override
  52. Future<void> onRequest(
  53. RequestOptions options,
  54. RequestInterceptorHandler handler,
  55. ) async {
  56. final String? token = await LocalStorage.getString(LocalStorageKey.access_token);
  57. if (token != null && !options.path.contains('authenticate')) {
  58. options.headers.putIfAbsent('Authorization', () => 'Bearer $token');
  59. }
  60. return handler.next(options);
  61. }
  62. }
  63. class HttpLogInterceptor extends InterceptorsWrapper {
  64. @override
  65. Future<void> onRequest(RequestOptions options, RequestInterceptorHandler handler) async {
  66. log('⭐⭐⭐⭐⭐⭐ onRequest: ${options.uri}\n'
  67. 'data=${options.data is Map ? json.encode(options.data) : options.data}\n'
  68. 'method=${options.method}\n'
  69. 'headers=${options.headers}\n'
  70. 'queryParameters=${options.queryParameters}');
  71. return handler.next(options);
  72. }
  73. @override
  74. void onResponse(Response<dynamic> response, ResponseInterceptorHandler handler) {
  75. // log('🍏🍏🍏🍏🍏🍏 onResponse: ${response.requestOptions.uri}\n'
  76. // 'statusCode=${response.statusCode}\n'
  77. // 'data=${response.data is Map ? json.encode(response.data) : response.data}');
  78. return handler.next(response);
  79. }
  80. @override
  81. void onError(DioError err, ErrorInterceptorHandler handler) {
  82. log('🔥🔥🔥🔥🔥🔥 onError: ${err.response?.requestOptions.uri}\n'
  83. 'errorStatusCode=${err.response?.statusCode}\n'
  84. 'errorResponseHeaders=${err.response?.headers}\n'
  85. 'errorMessage=${err.message}\n'
  86. 'errorData=${err.response?.data}');
  87. return handler.next(err);
  88. }
  89. }
  90. class LogoutInterceptor extends InterceptorsWrapper {
  91. @override
  92. Future<void> onRequest(
  93. RequestOptions options,
  94. RequestInterceptorHandler handler,
  95. ) async {
  96. final headers = options.headers;
  97. final String? token = await LocalStorage.getString(LocalStorageKey.access_token);
  98. if (token == null && headers.containsKey('Authorization')) {
  99. headers.remove('Authorization');
  100. }
  101. return handler.next(options);
  102. }
  103. }
  104. class UnauthorizedInterceptor extends InterceptorsWrapper {
  105. @override
  106. Future<void> onError(
  107. DioError err,
  108. ErrorInterceptorHandler handler,
  109. ) async {
  110. final checkUnauthorized =
  111. err.type == DioErrorType.response && err.response?.statusCode == HttpStatus.unauthorized && !err.requestOptions.path.contains('authenticate');
  112. if (checkUnauthorized) {
  113. // LocalStorage.clearUserInfo();
  114. // getx.Get.offAll(() => const LoginPage());
  115. // BlocProvider.of<AuthenticationBloc>(globalNavigator.currentContext!).add(
  116. // const AuthenticationStatusChanged(AuthenticationStatus.unauthenticated),
  117. // );
  118. // globalNavigator.currentState?.pushAndRemoveUntil<void>(
  119. // Routes.login(),
  120. // (route) => false,
  121. // );
  122. // BlocProvider.of<AuthenticationBloc>(globalNavigator.currentContext!).add(AuthenticationLogoutRequested());
  123. _logout();
  124. }
  125. return handler.next(err);
  126. }
  127. _logout() async {
  128. var pref = LocalPref();
  129. UserRepository _userRepository = UserRepository();
  130. globalNavigator.currentState?.pushAndRemoveUntil<void>(
  131. Routes.login(),
  132. (route) => false,
  133. );
  134. if (globalNavigator.currentContext != null) {
  135. BlocProvider.of<AuthenticationBloc>(globalNavigator.currentContext!).add(AuthenticationLogoutRequested());
  136. }
  137. try {
  138. String pushKey = await pref.getString(DATA_CONST.PUSH_KEY);
  139. if (pushKey.isNotEmpty) {
  140. _userRepository.deleteFcmToken(pushKey).then((value) {}).catchError((err) {}).whenComplete(() {
  141. pref.saveString(DATA_CONST.TOKEN_KEY, "");
  142. pref.saveString(DATA_CONST.PUSH_KEY, "");
  143. pref.saveString(DATA_CONST.CURRENT_FULL_NAME, "");
  144. LocalStorage.save(LocalStorageKey.full_name, '');
  145. });
  146. }
  147. } catch (e) {
  148. pref.saveString(DATA_CONST.CURRENT_FULL_NAME, "");
  149. LocalStorage.save(LocalStorageKey.full_name, '');
  150. pref.saveString(DATA_CONST.TOKEN_KEY, "");
  151. pref.saveString(DATA_CONST.PUSH_KEY, "");
  152. }
  153. }
  154. }
  155. // class DioProvider {
  156. // static Dio dio = Dio();
  157. // static FlavorValues flavorValues = FlavorConfig.values;
  158. // static Dio instance() {
  159. // dio.options.baseUrl = flavorValues.baseUrl;
  160. // (dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
  161. // (HttpClient client) {
  162. // client.badCertificateCallback =
  163. // (X509Certificate cert, String host, int port) => true;
  164. // return client;
  165. // };
  166. // dio.interceptors.add(
  167. // InterceptorsWrapper(
  168. // onRequest: (options, handler) {
  169. // var token = LocalStorage.getString(LocalStorageKey.access_token);
  170. // var refreshTokenUrl =
  171. // FlavorConfig.values.baseUrl + EndpointUrl.refreshToken;
  172. // if (token.isNotEmpty && (options.path != refreshTokenUrl)) {
  173. // options.headers['Authorization'] = 'Bearer $token';
  174. // }
  175. // options.headers['Content-Type'] = 'application/json';
  176. // options.headers['accept'] = 'application/json';
  177. // options.connectTimeout = 60000;
  178. // options.receiveTimeout = 60000;
  179. // log('⭐⭐⭐⭐⭐⭐ onRequest: ${options.uri}\n'
  180. // 'data=${options.data}\n'
  181. // 'method=${options.method}\n'
  182. // // 'headers=${options.headers}\n'
  183. // 'queryParameters=${options.queryParameters}');
  184. // return handler.next(options);
  185. // },
  186. // onResponse: (response, handler) async {
  187. // // log('🍏🍏🍏🍏🍏🍏 onResponse: $response');
  188. // return handler.next(response);
  189. // },
  190. // onError: (DioError e, handler) async {
  191. // log('🔥🔥🔥🔥🔥🔥 onError: $e\n'
  192. // 'Response: ${e.response}');
  193. // if (e.response != null) {
  194. // await refreshToken(e, handler);
  195. // } else {
  196. // handler.next(e);
  197. // }
  198. // },
  199. // ),
  200. // );
  201. // return dio;
  202. // }
  203. // static void logoutAndNavigationToSplashScreen() {
  204. // LocalStorage.clearUserInfo();
  205. // BlocProvider.of<AuthenticationBloc>(globalNavigator.currentContext!).add(
  206. // const AuthenticationStatusChanged(
  207. // AuthenticationStatus.unauthenticated,
  208. // ),
  209. // );
  210. // }
  211. // static Future<void> refreshToken(
  212. // DioError e, ErrorInterceptorHandler handler) async {
  213. // try {
  214. // var isCancelPreviousRequest = false;
  215. // var isRefreshSuccess = false;
  216. // if (e.response?.statusCode == 401) {
  217. // try {
  218. // var url = FlavorConfig.values.baseUrl + EndpointUrl.login;
  219. // var refreshToken =
  220. // LocalStorage.getString(LocalStorageKey.refresh_token);
  221. // var username = LocalStorage.getString(LocalStorageKey.username);
  222. // var res = await dio.post(url, data: {
  223. // 'token': refreshToken,
  224. // 'username': username,
  225. // });
  226. // if (res.statusCode == 200) {
  227. // var data = ResponseUser.fromJson(res.data);
  228. // LocalStorage.saveUserInfo(data, username);
  229. // isRefreshSuccess = true;
  230. // } else {
  231. // logoutAndNavigationToSplashScreen();
  232. // }
  233. // } catch (e) {
  234. // logoutAndNavigationToSplashScreen();
  235. // }
  236. // } else {
  237. // handler.next(e);
  238. // }
  239. // if (isRefreshSuccess) {
  240. // var token = LocalStorage.getString(LocalStorageKey.access_token);
  241. // e.requestOptions.headers['Authorization'] = 'Bearer $token';
  242. // e.requestOptions.headers['Content-Type'] = 'application/json';
  243. // e.requestOptions.headers['accept'] = 'application/json';
  244. // e.requestOptions.connectTimeout = 60000;
  245. // e.requestOptions.receiveTimeout = 60000;
  246. // final opts = Options(
  247. // method: e.requestOptions.method,
  248. // headers: e.requestOptions.headers,
  249. // );
  250. // try {
  251. // final cloneReq = await dio.request(
  252. // e.requestOptions.path,
  253. // options: opts,
  254. // data: e.requestOptions.data,
  255. // queryParameters: e.requestOptions.queryParameters,
  256. // );
  257. // return handler.resolve(cloneReq);
  258. // } catch (ex) {
  259. // print(ex);
  260. // if (!isCancelPreviousRequest) {
  261. // isCancelPreviousRequest = true;
  262. // handler.next(e);
  263. // }
  264. // }
  265. // }
  266. // } catch (e) {
  267. // print(e);
  268. // }
  269. // }
  270. // }