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.

247 lines
8.5KB

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