You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			301 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Dart
		
	
			
		
		
	
	
			301 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Dart
		
	
| import 'dart:async';
 | |
| import 'dart:convert';
 | |
| import 'dart:io';
 | |
| 
 | |
| import 'package:flutter/foundation.dart';
 | |
| import 'package:hmg_patient_app_new/services/api_exception.dart';
 | |
| import 'package:http/http.dart';
 | |
| import 'package:http/io_client.dart';
 | |
| 
 | |
| import '../core/app_state.dart';
 | |
| import '../core/consts.dart';
 | |
| import '../core/utils/utils.dart';
 | |
| import '../main.dart';
 | |
| 
 | |
| // ignore_for_file: avoid_annotating_with_dynamic
 | |
| 
 | |
| typedef FactoryConstructor<U> = U Function(dynamic);
 | |
| 
 | |
| class APIError {
 | |
|   int? errorCode;
 | |
|   String? errorMessage;
 | |
| 
 | |
|   APIError(this.errorCode, this.errorMessage);
 | |
| 
 | |
|   Map<String, dynamic> toJson() => {'errorCode': errorCode, 'errorMessage': errorMessage};
 | |
| 
 | |
|   @override
 | |
|   String toString() {
 | |
|     return jsonEncode(this);
 | |
|   }
 | |
| }
 | |
| 
 | |
| APIException _throwAPIException(Response response, Function retryCallBack) {
 | |
|   switch (response.statusCode) {
 | |
|     case 200:
 | |
|       APIError? apiError;
 | |
|       if (response.body != null && response.body.isNotEmpty) {
 | |
|         var jsonError = jsonDecode(response.body);
 | |
|         print(jsonError);
 | |
|         apiError = APIError(jsonError['ErrorCode'], jsonError['ErrorMessage']);
 | |
|       }
 | |
|       return APIException(APIException.BAD_REQUEST, error: apiError);
 | |
|     case 400:
 | |
|       APIError? apiError;
 | |
|       if (response.body != null && response.body.isNotEmpty) {
 | |
|         var jsonError = jsonDecode(response.body);
 | |
|         apiError = APIError(jsonError['ErrorCode'], jsonError['ErrorMessage']);
 | |
|       }
 | |
|       return APIException(APIException.BAD_REQUEST, error: apiError);
 | |
|     case 401:
 | |
|       return APIException(APIException.UNAUTHORIZED);
 | |
|     case 403:
 | |
|       return APIException(APIException.FORBIDDEN);
 | |
|     case 404:
 | |
|       return APIException(APIException.NOT_FOUND);
 | |
|     case 500:
 | |
|       return APIException(APIException.INTERNAL_SERVER_ERROR);
 | |
|     case 444:
 | |
|       var downloadUrl = response.headers["location"];
 | |
|       return APIException(APIException.UPGRADE_REQUIRED, arguments: downloadUrl);
 | |
|     default:
 | |
|       return APIException(APIException.OTHER);
 | |
|   }
 | |
| }
 | |
| 
 | |
| abstract class IApiClient {
 | |
|   Future<U> postJsonForObject<T, U>(FactoryConstructor<U> factoryConstructor, String url, T jsonObject,
 | |
|       {String? token, Map<String, dynamic>? queryParameters, Map<String, String>? headers, int retryTimes = 0, bool isFormData = false});
 | |
| 
 | |
|   Future<Response> postJsonForResponse<T>(String url, T jsonObject, {String? token, Map<String, dynamic>? queryParameters, Map<String, String>? headers, int retryTimes = 0, bool isFormData = false});
 | |
| 
 | |
|   Future<Response> getJsonForResponse<T>(String url, {String? token, Map<String, dynamic>? queryParameters, Map<String, String>? headers, int retryTimes = 0});
 | |
| 
 | |
|   void setHomeUrl(String url);
 | |
| }
 | |
| 
 | |
| class ApiClient implements IApiClient {
 | |
|   // static final ApiClient _instance = ApiClient._internal();
 | |
| 
 | |
|   // ApiClient._internal();
 | |
| 
 | |
|   // factory ApiClient() => _instance;
 | |
| 
 | |
|   @override
 | |
|   Future<U> postJsonForObject<T, U>(FactoryConstructor<U> factoryConstructor, String url, T jsonObject,
 | |
|       {String? token, Map<String, dynamic>? queryParameters, Map<String, String>? headers, int retryTimes = 0, bool isFormData = false}) async {
 | |
|     var _headers = {'Accept': 'application/json'};
 | |
|     if (headers != null && headers.isNotEmpty) {
 | |
|       _headers.addAll(headers);
 | |
|     }
 | |
|     if (!kReleaseMode) {
 | |
|       print("Url:$url");
 | |
|       var bodyJson = json.encode(jsonObject);
 | |
|       print("body:$bodyJson");
 | |
|     }
 | |
|     var response = await postJsonForResponse(url, jsonObject, token: token, queryParameters: queryParameters, headers: _headers, retryTimes: retryTimes, isFormData: isFormData);
 | |
|     // try {
 | |
|     if (!kReleaseMode) {
 | |
|       logger.i("res: " + response.body);
 | |
|     }
 | |
|     var jsonData = jsonDecode(response.body);
 | |
|     if (jsonData["IsAuthenticated"] != null) {
 | |
|       AppState().setIsAuthenticated = jsonData["IsAuthenticated"];
 | |
|     }
 | |
|     if (jsonData["ErrorMessage"] == null) {
 | |
|       return factoryConstructor(jsonData);
 | |
|     } else {
 | |
|       APIError? apiError;
 | |
|       apiError = APIError(jsonData['ErrorCode'], jsonData['ErrorEndUserMessage']);
 | |
|       throw APIException(APIException.BAD_REQUEST, error: apiError);
 | |
|     }
 | |
|     // } catch (ex) {
 | |
|     //   if (ex is APIException) {
 | |
|     //     rethrow;
 | |
|     //   } else {
 | |
|     //     throw APIException(APIException.BAD_RESPONSE_FORMAT, arguments: ex);
 | |
|     //   }
 | |
|     // }
 | |
|   }
 | |
| 
 | |
|   @override
 | |
|   Future<Response> postJsonForResponse<T>(String url, T jsonObject,
 | |
|       {String? token,
 | |
|       Map<String, dynamic>? queryParameters,
 | |
|       Map<String, String>? headers,
 | |
|       int retryTimes = 0,
 | |
|       bool isFormData = false,
 | |
|       bool isAuthAPI = false,
 | |
|       bool isHISAPI = false,
 | |
|       bool isSanedAPI = false,
 | |
|       bool isPutRequest = false}) async {
 | |
|     String? requestBody;
 | |
|     late Map<String, String> stringObj;
 | |
|     if (jsonObject != null) {
 | |
|       requestBody = jsonEncode(jsonObject);
 | |
|       if (headers == null) {
 | |
|         headers = {'Content-Type': 'application/json'};
 | |
|       } else {
 | |
|         headers['Content-Type'] = 'application/json';
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     return await _postForResponse(url, requestBody, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes);
 | |
|   }
 | |
| 
 | |
|   Future<Response> _postForResponse(String url, requestBody, {String? token, Map<String, dynamic>? queryParameters, Map<String, String>? headers, int retryTimes = 0}) async {
 | |
|     try {
 | |
|       var _headers = <String, String>{};
 | |
|       // if (token != null) {
 | |
|       //   _headers['Authorization'] = 'Bearer $token';
 | |
|       // }
 | |
| 
 | |
|       if (headers != null && headers.isNotEmpty) {
 | |
|         _headers.addAll(headers);
 | |
|       }
 | |
|       if (queryParameters != null) {
 | |
|         // var queryString = new Uri(queryParameters: queryParameters).query;
 | |
|         var queryString = Uri(queryParameters: queryParameters.map((key, value) => MapEntry(key, value == null ? null : value.toString()))).query;
 | |
|         url = url + '?' + queryString;
 | |
|       }
 | |
| 
 | |
|       // if (!kReleaseMode && url.contains("saned")) {
 | |
|       if (!kReleaseMode) {
 | |
|         print("Url: $url");
 | |
|         print("Headers: $_headers");
 | |
|         // var bodyJson = json.encode(requestBody);
 | |
|         print("body: $requestBody");
 | |
|       }
 | |
| 
 | |
|       var response = await _post(Uri.parse(url), body: requestBody, headers: _headers).timeout(Duration(seconds: 120));
 | |
| 
 | |
|       if (response.statusCode >= 200 && response.statusCode < 300) {
 | |
|         return response;
 | |
|       } else {
 | |
|         throw _throwAPIException(response, () {
 | |
|           // _postForResponse(url, requestBody, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes, isAuthAPI: isAuthAPI);
 | |
|           postJsonForResponse(url, requestBody);
 | |
|         });
 | |
|       }
 | |
|     } on SocketException catch (e) {
 | |
|       if (retryTimes > 0) {
 | |
|         print('will retry after 3 seconds...');
 | |
|         await Future.delayed(Duration(seconds: 3));
 | |
|         return await _postForResponse(url, requestBody, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1);
 | |
|       } else {
 | |
|         throw APIException(APIException.OTHER, arguments: e);
 | |
|       }
 | |
|     } on HttpException catch (e) {
 | |
|       if (retryTimes > 0) {
 | |
|         print('will retry after 3 seconds...');
 | |
|         await Future.delayed(Duration(seconds: 3));
 | |
|         return await _postForResponse(url, requestBody, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1);
 | |
|       } else {
 | |
|         throw APIException(APIException.OTHER, arguments: e);
 | |
|       }
 | |
|     } on TimeoutException catch (e) {
 | |
|       throw APIException(APIException.TIMEOUT, arguments: e);
 | |
|     } on ClientException catch (e) {
 | |
|       if (retryTimes > 0) {
 | |
|         print('will retry after 3 seconds...');
 | |
|         await Future.delayed(Duration(seconds: 3));
 | |
|         return await _postForResponse(url, requestBody, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1);
 | |
|       } else {
 | |
|         throw APIException(APIException.OTHER, arguments: e);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   @override
 | |
|   Future<Response> getJsonForResponse<T>(String url, {String? token, Map<String, dynamic>? queryParameters, Map<String, String>? headers, int retryTimes = 0, bool isAuthAPI = false}) async {
 | |
|     logger.i("Url:$url");
 | |
|     if (headers == null) {
 | |
|       headers = {'Content-Type': 'application/json'};
 | |
|     } else {
 | |
|       headers['Content-Type'] = 'application/json';
 | |
|     }
 | |
|     return await _getForResponse(url, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes, isAuthAPI: isAuthAPI);
 | |
|   }
 | |
| 
 | |
|   Future<Response> _getForResponse(String url, {String? token, Map<String, dynamic>? queryParameters, Map<String, String>? headers, int retryTimes = 0, bool isAuthAPI = false}) async {
 | |
|     try {
 | |
|       var _headers = <String, String>{};
 | |
|       if (token != null) {
 | |
|         _headers['Authorization'] = 'Bearer $token';
 | |
|       }
 | |
| 
 | |
|       if (headers != null && headers.isNotEmpty) {
 | |
|         _headers.addAll(headers);
 | |
|       }
 | |
| 
 | |
|       if (isAuthAPI) {
 | |
|         String token = await Utils.getStringFromPrefs(SharedPrefsConsts.appAuthToken);
 | |
|         _headers['Authorization'] = "Bearer $token";
 | |
|       }
 | |
| 
 | |
|       if (queryParameters != null) {
 | |
|         var queryString = new Uri(queryParameters: queryParameters).query;
 | |
|         url = url + '?' + queryString;
 | |
|       }
 | |
|       var response = await _get(Uri.parse(url), headers: _headers).timeout(Duration(seconds: 60));
 | |
| 
 | |
|       if (response.statusCode >= 200 && response.statusCode < 300) {
 | |
|         return response;
 | |
|       } else {
 | |
|         throw _throwAPIException(response, () {
 | |
|           _getForResponse(url, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes);
 | |
|         });
 | |
|       }
 | |
|     } on SocketException catch (e) {
 | |
|       if (retryTimes > 0) {
 | |
|         print('will retry after 3 seconds...');
 | |
|         await Future.delayed(Duration(seconds: 3));
 | |
|         return await _getForResponse(url, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1);
 | |
|       } else {
 | |
|         throw APIException(APIException.OTHER, arguments: e);
 | |
|       }
 | |
|     } on HttpException catch (e) {
 | |
|       if (retryTimes > 0) {
 | |
|         print('will retry after 3 seconds...');
 | |
|         await Future.delayed(Duration(seconds: 3));
 | |
|         return await _getForResponse(url, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1);
 | |
|       } else {
 | |
|         throw APIException(APIException.OTHER, arguments: e);
 | |
|       }
 | |
|     } on TimeoutException catch (e) {
 | |
|       throw APIException(APIException.TIMEOUT, arguments: e);
 | |
|     } on ClientException catch (e) {
 | |
|       if (retryTimes > 0) {
 | |
|         print('will retry after 3 seconds...');
 | |
|         await Future.delayed(Duration(seconds: 3));
 | |
|         return await _getForResponse(url, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1);
 | |
|       } else {
 | |
|         throw APIException(APIException.OTHER, arguments: e);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Future<Response> _get(url, {Map<String, String>? headers}) => _withClient((client) => client.get(url, headers: headers));
 | |
| 
 | |
|   bool _certificateCheck(X509Certificate cert, String host, int port) => true;
 | |
| 
 | |
|   Future<T> _withClient<T>(Future<T> Function(Client) fn) async {
 | |
|     var httpClient = HttpClient()..badCertificateCallback = _certificateCheck;
 | |
|     var client = IOClient(httpClient);
 | |
|     try {
 | |
|       return await fn(client);
 | |
|     } finally {
 | |
|       client.close();
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Future<Response> _post(url, {Map<String, String>? headers, body, Encoding? encoding}) => _withClient((client) => client.post(url, headers: headers, body: body, encoding: encoding));
 | |
| 
 | |
|   Future<Response> _put(url, {Map<String, String>? headers, body, Encoding? encoding}) => _withClient((client) => client.put(url, headers: headers, body: body, encoding: encoding));
 | |
| 
 | |
|   @override
 | |
|   void setHomeUrl(String url) {
 | |
|     // TODO: implement setHomeUrl
 | |
|   }
 | |
| }
 |