import 'dart:convert' show jsonDecode, jsonEncode; import 'package:fotodocumentation/dto/base_dto.dart'; import 'package:fotodocumentation/utils/di_container.dart'; import 'package:fotodocumentation/utils/http_client_utils.dart'; import 'package:fotodocumentation/utils/jwt_token_storage.dart'; import 'package:fotodocumentation/utils/url_utils.dart'; import 'package:http/http.dart' as http; import 'package:http/http.dart' show Response; import 'package:fotodocumentation/main.dart' show logger; abstract class BaseController { UrlUtils get uriUtils => DiContainer.get(); JwtTokenStorage get _jwtTokenStorage => DiContainer.get(); HttpClientUtils get httpClientUtils => DiContainer.get(); Future
getAuthHeader() async { final accessToken = await _jwtTokenStorage.getAccessToken(); if (accessToken != null && accessToken.isNotEmpty) { // Use JWT Bearer token return Header('Authorization', 'Bearer $accessToken'); } else { return const Header("Accept-Language", "en-US"); } } Exception getServerError(Response response) { return Exception("Error receiving data from server"); } Future> runGetListWithAuth(String uriStr, List Function(dynamic) convert) async { http.Client client = httpClientUtils.client; try { Header cred = await getAuthHeader(); Uri uri = Uri.parse(uriStr); var response = await client.get(uri, headers: {cred.name: cred.value}); if (response.statusCode == 200) { String text = response.body; var jsonArray = jsonDecode(text); return convert(jsonArray); } else { throw ServerError(response.statusCode); // Exception("Failed to get server data ${response.statusCode}"); } } catch (e) { logger.e("exception $e"); rethrow; } } Future runGetWithAuth(String uriStr, T Function(dynamic) convert) async { http.Client client = httpClientUtils.client; try { Header cred = await getAuthHeader(); Uri uri = Uri.parse(uriStr); var response = await client.get(uri, headers: {cred.name: cred.value}); if (response.statusCode == 200) { String text = response.body; var jsonArray = jsonDecode(text); return convert(jsonArray); } else { throw ServerError(response.statusCode); // Exception("Failed to get server data ${response.statusCode}"); } } catch (e) { logger.e("exception $e"); rethrow; } } Future runDeleteWithAuth(String uriStr) async { http.Client client = httpClientUtils.client; Header cred = await getAuthHeader(); Uri uri = Uri.parse(uriStr); var response = await client.delete(uri, headers: {cred.name: cred.value}); return response.statusCode == 200; } Future runPutWithAuth(String uriStr) async { http.Client client = httpClientUtils.client; Header cred = await getAuthHeader(); Uri uri = Uri.parse(uriStr); var response = await client.put(uri, headers: {cred.name: cred.value}); return response.statusCode == 200; } Future> runSaveNew(String uriStr, T dtoObj, Function(http.Response response, T dto) processReply) async { http.Client client = httpClientUtils.client; try { Header cred = await getAuthHeader(); String body = jsonEncode(dtoObj.toMap()); Uri uri = Uri.parse(uriStr); var response = await client.post(uri, headers: {cred.name: cred.value, "Accept": "application/json", "Content-Type": "application/json"}, body: body); return processReply(response, dtoObj); } catch (e) { logger.e("exception $e"); } return ServerReply(ServerState.error, dtoObj); } Future> runSaveUpdate(String uriStr, T dtoObj, Function(http.Response response, T dto) processReply) async { http.Client client = httpClientUtils.client; try { Header cred = await getAuthHeader(); String body = jsonEncode(dtoObj.toMap()); Uri uri = Uri.parse(uriStr); var response = await client.put(uri, headers: {cred.name: cred.value, "Accept": "application/json", "Content-Type": "application/json"}, body: body); return processReply(response, dtoObj); } catch (e) { logger.e("exception $e"); } return ServerReply(ServerState.error, dtoObj); } ServerReply processServerResponse(Response response, T dto, T Function(Map json) fromJson) { if (response.statusCode == 200) { String text = response.body; var json = jsonDecode(text); var dto = fromJson(json); return ServerReply(ServerState.ok, dto); } else if (response.statusCode == 400 || response.statusCode == 409) { String text = response.body; try { var json = jsonDecode(text); var error = ErrorDto.fromJson(json); return ServerReply(ServerState.duplicate, dto, error: error); } catch (e) { return ServerReply(ServerState.error, dto, error: ErrorDto(response.statusCode, text)); } } else if (response.statusCode == 403) { var error = ErrorDto(403, "Not allowed."); return ServerReply(ServerState.error, dto, error: error); } return ServerReply(ServerState.error, dto, error: ErrorDto(response.statusCode, "Internal server error")); } } class Header { final String name; final String value; const Header(this.name, this.value); @override String toString() => '$runtimeType: $name, $value'; } class ServerReply { ServerState state; T entity; ErrorDto? error; ServerReply(this.state, this.entity, {this.error}); @override String toString() => '$runtimeType: $state, $entity, $error'; } class ServerError { int statusCode; ServerError(this.statusCode); } enum ServerState { ok, duplicate, error, ; }