This repository has been archived on 2024-10-18. You can view files and clone it, but cannot push or open issues or pull requests.
ftc_patient_app/lib/web_services/http_request_client.dart

775 lines
24 KiB
Dart

import 'dart:async';
import 'dart:convert';
import 'dart:developer';
import 'dart:io';
import 'dart:typed_data';
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:ftc_mobile_app/utilities/enums/api_method.dart';
import 'package:http/http.dart' as http;
import 'package:ftc_mobile_app/ftc_mobile_app.dart';
import 'package:http_parser/src/media_type.dart';
import '../dialogs/app_dialogs.dart';
import 'logging_interceptor.dart';
class HttpRequestClient {
HttpRequestClient._();
static final HttpRequestClient _instance = HttpRequestClient._();
factory HttpRequestClient() {
return _instance;
}
static const int _kSecondsTimeout = 60;
static const String _kTimeOutMessage = "Unable to process request";
static const String _kInternetIssue =
"Your internet connection is not stable";
static const String _kOtherException = "Unable to process request";
Map<String, dynamic> errorResponse(String message) {
return Map.of({"success": false, "message": message});
}
Map<String, dynamic> _dioErrorHandler(DioException e) {
if (e.type == DioExceptionType.connectionError) {
return errorResponse(_kInternetIssue);
}
// The request was made and the server responded with a status code
// that falls out of the range of 2xx and is also not 304.
if (e.response != null) {
debugPrint('Dio error!');
debugPrint('STATUS: ${e.response?.statusCode}');
debugPrint('DATA: ${e.response?.data}');
debugPrint('HEADERS: ${e.response?.headers}');
if (e.response!.statusCode == HttpStatus.unauthorized ||
e.response!.statusCode == HttpStatus.forbidden) {
AppDialog.showUnauthorizedAlert();
return errorResponse('');
}
if (e.response!.data != null &&
e.response!.data is Map &&
(e.response!.data as Map).containsKey('message')) {
return errorResponse(e.response!.data['message'].toString());
}
// if (e.response!.statusCode == 401) {
// return decoder(errorResponse(e.response!.data.toString()));
// }
} else {
// Error due to setting up or sending the request
debugPrint('Error sending request!');
debugPrint(e.message);
}
debugPrint('Dio ERROR ${e.error}\n');
return errorResponse(_kOtherException);
}
Map<String, dynamic> exceptionHandler(e) {
debugPrint("Web Error: $e");
debugPrint("e Type: ${e.runtimeType.toString()}");
if (e is SocketException) {
return errorResponse(_kInternetIssue);
} else if (e is TimeoutException) {
return errorResponse(_kInternetIssue);
} else if (e is FormatException) {
return errorResponse(_kOtherException);
} else {
return errorResponse(_kOtherException);
}
}
//----------------------------------------------------------------
Future<ResponseModel> getRequestWithOutHeader({required String url}) async {
try {
http.Response response = await http
.get(
Uri.parse(url),
)
.timeout(
const Duration(
seconds: _kSecondsTimeout,
),
);
ResponseModel responseModel = ResponseModel();
if (response.body.isNotEmpty && response.body.length > 4) {
responseModel.statusCode = response.statusCode;
responseModel.statusDescription = "Success";
responseModel.data = response.body;
}
// log('----------------response model is---------------${responseModel.toString()}');
return responseModel;
} on TimeoutException catch (e) {
return Future.value(
ResponseModel.named(
statusCode: 408,
statusDescription: _kTimeOutMessage,
data: e.toString(),
),
);
} on SocketException catch (e) {
return Future.value(
ResponseModel.named(
statusCode: 400,
statusDescription: _kInternetIssue,
data: e.toString(),
),
);
} catch (e) {
return Future.value(
ResponseModel.named(
statusCode: 500,
statusDescription: _kOtherException,
data: e.toString(),
),
);
}
}
Future<ResponseModel> getRequestWithRequestBody({
required String url,
dynamic requestBody,
Map<String, String>? requestHeader,
}) async {
try {
Map<String, String> header = {};
if (requestHeader == null) {
header = await getRequestHeader();
}
final uri = Uri.parse(url);
final uriWithBody = uri.replace(
queryParameters: requestBody,
);
http.Response response = await http
.get(
uriWithBody,
headers: requestHeader ?? header,
)
.timeout(
const Duration(
seconds: _kSecondsTimeout,
),
);
ResponseModel responseModel = ResponseModel();
if ((response.statusCode >= 200 && response.statusCode <= 230)) {
responseModel = ResponseModel.fromJson(
jsonDecode(response.body),
statusCode: response.statusCode,
);
} else {
responseModel = ResponseModel.errorFromJson(
jsonDecode(response.body),
statusCode: response.statusCode,
);
}
// log('----------------response model is---------------${responseModel.toString()}');
return responseModel;
} on TimeoutException catch (e) {
return Future.value(
ResponseModel.named(
statusCode: 408,
statusDescription: _kTimeOutMessage,
data: e.toString(),
),
);
} on SocketException catch (e) {
return Future.value(
ResponseModel.named(
statusCode: 400,
statusDescription: _kInternetIssue,
data: e.toString(),
),
);
} catch (e) {
return Future.value(
ResponseModel.named(
statusCode: 500,
statusDescription: _kOtherException,
data: e.toString(),
),
);
}
}
Future<ResponseModel> postRequest({
required String url,
dynamic requestBody,
bool doJsonEncodeRequestBody = false,
bool isTokenRequired = false,
dynamic requestHeader,
}) async {
try {
ResponseModel responseModel = ResponseModel();
Map<String, String> header = {};
if (isTokenRequired) {
header = await getRequestHeader(isBearer: true);
}
http.Response response = await http
.post(
Uri.parse(url),
body:
doJsonEncodeRequestBody ? jsonEncode(requestBody) : requestBody,
headers: isTokenRequired ? header : requestHeader,
)
.timeout(
const Duration(
seconds: _kSecondsTimeout,
),
);
if ((response.statusCode >= 200 && response.statusCode <= 230)) {
responseModel = ResponseModel.fromJson(
jsonDecode(response.body),
statusCode: response.statusCode,
);
} else {
responseModel = ResponseModel.errorFromJson(
jsonDecode(response.body),
statusCode: response.statusCode,
);
}
// log('----------------response model is---------------${responseModel.toString()}');
return responseModel;
} on TimeoutException catch (e) {
return Future.value(
ResponseModel.named(
statusCode: 408,
statusDescription: _kTimeOutMessage,
data: e.toString(),
),
);
} on SocketException catch (e) {
return Future.value(
ResponseModel.named(
statusCode: 400,
statusDescription: _kInternetIssue,
data: e.toString(),
),
);
} catch (e) {
return Future.value(
ResponseModel.named(
statusCode: 500,
statusDescription: _kOtherException,
data: e.toString(),
),
);
}
}
Future<ResponseModel> uploadImageRequest({
required String url,
required String filePath,
}) async {
try {
ResponseModel responseModel = ResponseModel();
Map<String, String> header = {};
header = await getRequestHeader(isBearer: true);
http.MultipartRequest request = http.MultipartRequest(
"POST",
Uri.parse(url),
);
request.files.add(
await http.MultipartFile.fromPath(
"photo",
filePath,
),
);
request.headers.addAll(header);
http.StreamedResponse response = await request.send().timeout(
const Duration(
seconds: _kSecondsTimeout,
),
);
if ((response.statusCode >= 200 && response.statusCode <= 230)) {
responseModel = ResponseModel.fromJson(
jsonDecode(await response.stream.bytesToString()),
statusCode: response.statusCode,
);
} else {
responseModel = ResponseModel.errorFromJson(
jsonDecode(await response.stream.bytesToString()),
statusCode: response.statusCode,
);
}
// log('----------------response model is---------------${responseModel.toString()}');
return responseModel;
} on TimeoutException catch (e) {
return Future.value(
ResponseModel.named(
statusCode: 408,
statusDescription: _kTimeOutMessage,
data: e.toString(),
),
);
} on SocketException catch (e) {
return Future.value(
ResponseModel.named(
statusCode: 400,
statusDescription: _kInternetIssue,
data: e.toString(),
),
);
} catch (e) {
return Future.value(
ResponseModel.named(
statusCode: 500,
statusDescription: _kOtherException,
data: e.toString(),
),
);
}
}
Future<ResponseModel> patchRequest({
required String url,
dynamic requestBody,
bool isBearerHeaderRequired = false,
bool isContentType = true,
}) async {
try {
ResponseModel responseModel = ResponseModel();
Map<String, String> header = {};
if (isBearerHeaderRequired) {
header = await getRequestHeader(
isBearer: true,
isContentType: isContentType,
);
}
http.Request request = http.Request(
'PATCH',
Uri.parse(url),
);
request.body = jsonEncode(requestBody);
request.headers.addAll(header);
http.StreamedResponse response = await request.send().timeout(
const Duration(
seconds: _kSecondsTimeout,
),
);
if ((response.statusCode >= 200 && response.statusCode <= 230)) {
responseModel = ResponseModel.fromJson(
jsonDecode(await response.stream.bytesToString()),
statusCode: response.statusCode,
);
} else {
responseModel = ResponseModel.errorFromJson(
jsonDecode(await response.stream.bytesToString()),
statusCode: response.statusCode,
);
}
// log('----------------response model is---------------${responseModel.toString()}');
return responseModel;
} on TimeoutException catch (e) {
return Future.value(
ResponseModel.named(
statusCode: 408,
statusDescription: _kTimeOutMessage,
data: e.toString(),
),
);
} on SocketException catch (e) {
return Future.value(
ResponseModel.named(
statusCode: 400,
statusDescription: _kInternetIssue,
data: e.toString(),
),
);
} catch (e) {
return Future.value(
ResponseModel.named(
statusCode: 500,
statusDescription: _kOtherException,
data: e.toString(),
),
);
}
}
Future<ResponseModel> deleteRequest({
required String url,
bool isBearerHeaderRequired = false,
dynamic requestBody,
}) async {
try {
ResponseModel responseModel = ResponseModel();
Map<String, String> header = {};
if (isBearerHeaderRequired) {
header = await getRequestHeader(isBearer: true);
}
http.Request request = http.Request(
'DELETE',
Uri.parse(url),
);
request.headers.addAll(header);
if (requestBody != null) {
request.body = jsonEncode(requestBody);
}
http.StreamedResponse response = await request.send().timeout(
const Duration(
seconds: _kSecondsTimeout,
),
);
if ((response.statusCode >= 200 && response.statusCode <= 230)) {
responseModel = ResponseModel.fromJson(
jsonDecode(await response.stream.bytesToString()),
statusCode: response.statusCode,
);
} else {
responseModel = ResponseModel.errorFromJson(
jsonDecode(await response.stream.bytesToString()),
statusCode: response.statusCode,
);
}
// log('----------------response model is---------------${responseModel.toString()}');
return responseModel;
} on TimeoutException catch (e) {
return Future.value(
ResponseModel.named(
statusCode: 408,
statusDescription: _kTimeOutMessage,
data: e.toString(),
),
);
} on SocketException catch (e) {
return Future.value(
ResponseModel.named(
statusCode: 400,
statusDescription: _kInternetIssue,
data: e.toString(),
),
);
} catch (e) {
return Future.value(
ResponseModel.named(
statusCode: 500,
statusDescription: _kOtherException,
data: e.toString(),
),
);
}
}
Future<ResponseModel> customRequest(
String requestType, {
required String url,
bool isBearerHeaderRequired = false,
bool isBearer = true,
dynamic requestBody,
dynamic requestHeader,
}) async {
try {
ResponseModel responseModel = ResponseModel();
Map<String, String> header = {};
if (isBearerHeaderRequired) {
header = await getRequestHeader(isBearer: isBearer);
}
http.Request request = http.Request(
requestType,
Uri.parse(url),
);
request.headers.addAll(isBearerHeaderRequired ? header : requestHeader);
request.body = json.encode(requestBody);
log('--------------request.url----------------------------($requestType) ${request.url.origin}${request.url.path}');
log('--------------request.headers----------------------------${request.headers}');
log('--------------request.body----------------------------${request.body}');
http.StreamedResponse response = await request.send().timeout(
const Duration(
seconds: _kSecondsTimeout,
),
);
if ((response.statusCode >= 200 && response.statusCode <= 230)) {
responseModel = ResponseModel.fromJson(
jsonDecode(await response.stream.bytesToString()),
statusCode: response.statusCode,
);
log("Api Response($url):\n${jsonEncode(responseModel.toJson())}");
} else {
responseModel = ResponseModel.errorFromJson(
jsonDecode(await response.stream.bytesToString()),
statusCode: response.statusCode,
);
print("FUTURE Expection");
print(responseModel);
}
// log('----------------response model is---------------${responseModel.toString()}');
return responseModel;
} on TimeoutException catch (e) {
print("TimeOut Expection");
print(e);
return Future.value(
ResponseModel.named(
statusCode: 408,
statusDescription: _kTimeOutMessage,
data: e.toString(),
),
);
} on SocketException catch (e) {
print("SOCKET Expection");
print(e);
return Future.value(
ResponseModel.named(
statusCode: 400,
statusDescription: _kInternetIssue,
data: e.toString(),
),
);
} catch (e) {
print("FUTURE Expection");
print(e);
return Future.value(
ResponseModel.named(
statusCode: 500,
statusDescription: _kOtherException,
data: e.toString(),
),
);
}
}
Future<ResponseModel> uploadVideoRequest({
required String uploadUrl,
required Uint8List chunkStream,
}) async {
try {
ResponseModel responseModel = ResponseModel();
http.StreamedRequest request = http.StreamedRequest(
"PUT",
Uri.parse(uploadUrl),
);
request.headers.addAll({
'Content-Length': "${chunkStream.length}",
'Content-Type': 'video/mp4',
'content-type': 'application/octet-stream'
});
request.sink.add(chunkStream);
request.sink.close();
http.StreamedResponse response = await request.send();
responseModel.statusCode = response.statusCode;
responseModel.statusDescription = response.reasonPhrase ?? '';
responseModel.header = response.headers;
return responseModel;
} on TimeoutException catch (e) {
return Future.value(
ResponseModel.named(
statusCode: 408,
statusDescription: _kTimeOutMessage,
data: e.toString(),
),
);
} on SocketException catch (e) {
return Future.value(
ResponseModel.named(
statusCode: 400,
statusDescription: _kInternetIssue,
data: e.toString(),
),
);
} catch (e) {
return Future.value(
ResponseModel.named(
statusCode: 500,
statusDescription: _kOtherException,
data: e.toString(),
),
);
}
}
Future<Map<String, String>> getRequestHeader({
bool isBearer = true,
bool isContentType = true,
}) async {
// String token = SessionManagement().getSessionToken(
// tokenKey: SessionKeys.kUserTokenKey,
// );
//todo remove this in end
String token =
'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhIjp0cnVlLCJuIjoiSmFtc2hhaWQgU2FiaXIiLCJlIjoiamFtc2hhaWRzYWJpcjQxMTk4MEBnbWFpbC5jb20iLCJkIjoiNjQ2NTEyN2E3MmJjNzEzY2E4NDYwY2IzIiwicCI6Ii91cGxvYWRzL2RwL2RlZmF1bHQucG5nIiwiciI6Il9hIiwiaWF0IjoxNjkzMjIzNTIzfQ.EtpS_o0kEhdlNzCyFdFNNQzHd0IipTw8BEuUBVgfYok';
Map<String, String> header = {
'Authorization': isBearer ? 'Bearer $token' : token,
if (isContentType) 'Content-Type': 'application/json'
};
return header;
}
Future<dynamic> safeApiCall({
required ApiMethod method,
required String url,
Map<String, String>? headers,
Map? body,
Map<String, String>? param,
}) async {
try {
// final hasInternet = await FrequentFunctions.hasInternetConnection;
// debugPrint("hasInternet: $hasInternet");
//
// if (!hasInternet) {
// return decoder(errorResponse(errorMsgNoInternet));
// }
Map<String, String> customHeader = await getRequestHeader();
if(headers != null) customHeader.addAll(headers!);
final dio = Dio()
..interceptors.add(Logging())
..options.headers.addAll(customHeader);
if (headers != null) {
dio.options.headers.addAll(headers);
}
Response response;
switch (method) {
case ApiMethod.get:
response = await dio.get(url, queryParameters: param);
break;
case ApiMethod.post:
response = await dio.post(
url,
data: (body == null) ? null : json.encode(body),
queryParameters: param,
);
break;
case ApiMethod.put:
response = await dio.put(
url,
data: (body == null) ? null : json.encode(body),
queryParameters: param,
);
break;
case ApiMethod.patch:
response = await dio.patch(
url,
data: (body == null) ? null : json.encode(body),
queryParameters: param,
);
break;
case ApiMethod.delete:
response = await dio.delete(
url,
data: (body == null) ? null : json.encode(body),
queryParameters: param,
);
break;
}
return ResponseModel.fromJson(jsonDecode(response.toString()))
..statusCode = response.statusCode ?? 0;
} on DioException catch (e) {
return ResponseModel.named(
statusCode: e.response?.statusCode ?? 0,
statusDescription: _dioErrorHandler(e)['message'],
);
} catch (e) {
debugPrint("Web Error: $e");
return ResponseModel.named(
statusCode: 0,
statusDescription: exceptionHandler(e)['message'],
);
}
}
Future<ResponseModel> safeFormDataRequest({
required String url,
required FormData body,
}) async {
try {
Map<String, String> customHeader = await getRequestHeader();
final dio = Dio()
..interceptors.add(Logging())
..options.headers.addAll(customHeader);
final response = await dio.post(
url,
data: body,
onSendProgress: (int sent, int total) {
debugPrint('$sent $total');
},
);
return ResponseModel.fromJson(jsonDecode(response.toString()))
..statusCode = response.statusCode ?? 0;
} on DioException catch (e) {
return ResponseModel.named(
statusCode: e.response?.statusCode ?? 0,
statusDescription: _dioErrorHandler(e)['message'],
);
} catch (e) {
debugPrint("Web Error: $e");
return ResponseModel.named(
statusCode: 0,
statusDescription: exceptionHandler(e)['message'],
);
}
}
Future<ResponseModel> postMultipartRequest(
{required String url,
Map<String, String> fields = const {},
Map<String, String> files = const {}}) async {
try {
Map<String, String> customHeader = await getRequestHeader();
// customHeader['Connection'] = 'keep-alive';
// customHeader['Accept'] = 'application/json';
// customHeader['Content-Type'] = 'multipart/form-data';
http.MultipartRequest request =
http.MultipartRequest('POST', Uri.parse(url));
request.headers.addAll(customHeader);
request.fields.addAll(fields);
for (MapEntry<String, String> file in files.entries) {
String type = file.value.substring(file.value.lastIndexOf('.') + 1);
String name = file.value.substring(file.value.lastIndexOf('/') + 1);
request.files.add(await http.MultipartFile.fromPath(
file.key,
file.value,
filename: name,
contentType: MediaType('image', type),
));
}
http.StreamedResponse streamedResponse = await request.send();
http.Response httpResponse =
await http.Response.fromStream(streamedResponse);
log('────────────────────url> $url');
log('────────────────────files> $files');
log('────────────────────fields> $fields');
log('────────────────────Response.body> ${httpResponse.body}');
ResponseModel response =
ResponseModel.fromJson(jsonDecode(httpResponse.body));
return Future.value(response);
} on HttpException catch (e) {
return Future.value(ResponseModel.named(
statusCode: 405, statusDescription: e.message, data: e.toString()));
} on TimeoutException {
return Future.value(ResponseModel.named(
statusCode: 408,
statusDescription: "Request TimeOut",
data: "Request TimeOut"));
} on SocketException {
return Future.value(ResponseModel.named(
statusCode: 400,
statusDescription: "Bad Request",
data: "Bad Request"));
} catch (e) {
return Future.value(ResponseModel.named(
statusCode: 500,
statusDescription: "Service Error",
data: "Service Error"));
}
}
}