import 'dart:convert'; import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:workouttest_util/service/webapi.dart'; import 'package:workouttest_util/util/logging.dart'; import 'package:workouttest_util/util/common.dart'; import 'package:workouttest_util/util/not_found_exception.dart'; import 'package:workouttest_util/model/cache.dart'; class APIClient with Common, Logging { static final APIClient _singleton = APIClient._internal(); late bool cert; factory APIClient() { return _singleton; } APIClient._internal() { cert = false; } dynamic authenticateUser(String email, String password) async { if ( kIsWeb ) { APIWebClient webClient = APIWebClient(); return webClient.authenticateUser(email, password); } var baseUrl = Cache().getBaseUrl(); log("Base URL: $baseUrl"); var url = "${baseUrl}authenticate"; try { var uri = Uri.parse(url); HttpClient client = HttpClient(); final HttpClientRequest request = await client.postUrl(uri); request.headers.contentType = ContentType('application', 'json', charset: 'utf-8'); request.headers.set('Authorization', '1'); final body = jsonEncode({ 'username': email, 'password': password }); request.write(body); HttpClientResponse result = await request.close(); client.close(); if (result.statusCode != 200) { log("authentication response: ${result.statusCode} with URL: $url"); throw Exception("Authentication error: ${result.statusCode}"); } String response = await result.transform(utf8.decoder).join(); log("Authentication status: ${result.statusCode}, response: $response"); final data = jsonDecode(response); return data; } catch (exception) { log(exception.toString()); try { await Sentry.captureException(exception); } on Exception catch (e) { log(e.toString()); } throw Exception("Network error, try again later!"); } } Future post(String endPoint, String body) async { if ( kIsWeb ) { APIWebClient webClient = APIWebClient(); return webClient.post(endPoint, body); } final url = Cache().getBaseUrl() + endPoint; log(" ------------ http/post body $body - url: $url "); try { String authToken = Cache().getAuthToken(); if (authToken.isEmpty) { var responseJson = await authenticateUser(Cache.username, Cache.password); authToken = responseJson['token']; Cache().authToken = authToken; } var uri = Uri.parse(url); HttpClient client = HttpClient(); client.badCertificateCallback = ((X509Certificate cert, String host, int port) => true); final HttpClientRequest request = await client.postUrl(uri); request.headers.contentType = ContentType("application", "json", charset: "utf-8"); request.headers.set('Authorization', 'Bearer $authToken'); //request.contentLength = body.length; request.write(body); HttpClientResponse result = await request.close(); client.close(); log(" ------------post response code: ${result.statusCode}"); if (result.statusCode == 200) { return await result.transform(utf8.decoder).join(); } else if (result.statusCode == 404) { throw const NotFoundException(message: "Not Found"); } else { throw Exception("Network Error, please try again later"); } } on NotFoundException catch(e) { throw NotFoundException(message: "Not Found ${e.message}"); } on Exception catch (e) { log("Post Exception: $e"); await Sentry.captureException(e); throw Exception("Network Error, please try again later"); } } Future get(String endPoint, String param) async { if ( kIsWeb ) { APIWebClient webClient = APIWebClient(); return webClient.get(endPoint, param); } final url = Cache().getBaseUrl() + endPoint + param; try { log("-------- API get $url"); String authToken = Cache().getAuthToken(); if (authToken.isEmpty) { var responseJson = await authenticateUser(Cache.username, Cache.password); authToken = responseJson['token']; Cache().authToken = authToken; } var uri = Uri.parse(url); HttpClient client = HttpClient(); final HttpClientRequest request = await client.getUrl(uri); request.headers.contentType = ContentType("application", "json", charset: "utf-8"); request.headers.set('Authorization', 'Bearer $authToken'); request.write(""); HttpClientResponse result = await request.close(); client.close(); log(" ------------get response code: ${result.statusCode}"); if (result.statusCode == 200) { return await result.transform(utf8.decoder).join(); } else if (result.statusCode == 404) { throw const NotFoundException(message: "Not Found"); } else { throw Exception("Network Error, please try again later"); } } on NotFoundException catch(e) { throw NotFoundException(message: "Not Found ${e.message}"); } on Exception catch (e) { log("Post Exception: $e"); await Sentry.captureException(e); throw Exception("Network Error, please try again later"); } } }