import 'dart:io'; import 'package:comunic/helpers/events_helper.dart'; import 'package:comunic/helpers/preferences_helper.dart'; import 'package:comunic/models/api_request.dart'; import 'package:comunic/models/api_response.dart'; import 'package:comunic/models/config.dart'; import 'package:dio/dio.dart'; /// API Helper /// /// @author Pierre HUBERT class APIHelper { /// Execute a [request] on the server and returns a [APIResponse] /// /// This method should never throw but the response code of the [APIResponse] /// should be verified before accessing response content Future exec(APIRequest request, {bool multipart = false}) async { try { //Add API tokens request.addString("client", config().clientName); //Add user token (if required) if (request.needLogin) { final token = (await PreferencesHelper.getInstance())!.getLoginToken(); if (token == null) { EventsHelper.emit(InvalidLoginTokensEvent()); throw new Exception("No login token available!"); } request.addString("token", token); } // Determine server URL final path = config().apiServerUri + request.uri; Uri url; if (!config().apiServerSecure) url = Uri.http(config().apiServerName, path); else url = Uri.https(config().apiServerName, path); final data = FormData.fromMap(request.args!); // Process files (if required) if (multipart) { // Process filesystem files for (final key in request.files.keys) { var v = request.files[key]!; data.files.add(MapEntry( key, await MultipartFile.fromFile(v.path, filename: v.path.split("/").last))); } // Process in-memory files for (final key in request.bytesFiles.keys) { var v = request.bytesFiles[key]!; data.files.add(MapEntry( key, MultipartFile.fromBytes( v.bytes!, filename: v.filename.split("/").last, contentType: v.type, ))); } } // Execute the request final response = await Dio().post( url.toString(), data: data, cancelToken: request.cancelToken, onSendProgress: request.progressCallback, options: Options( receiveDataWhenStatusError: true, validateStatus: (s) => true, responseType: ResponseType.plain, ), ); // Check if login token is rejected by server if (response.statusCode == 412) EventsHelper.emit(InvalidLoginTokensEvent()); if (response.statusCode != HttpStatus.ok) return APIResponse(response.statusCode!, response.data); return APIResponse(response.statusCode!, response.data); } catch (e, stack) { print(e.toString()); print("Could not execute a request!"); print(stack); return APIResponse(-1, null); } } /// Same as exec, but also allows to send files Future execWithFiles(APIRequest request) async { return await exec(request, multipart: true); } }