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("serviceName", config().serviceName); request.addString("serviceToken", config().serviceToken); //Add user tokens (if required) if (request.needLogin) { final tokens = (await PreferencesHelper.getInstance()).getLoginTokens(); assert(tokens != null); request.addString("userToken1", tokens.tokenOne); request.addString("userToken2", tokens.tokenTwo); } // 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))); } } // Execute the request final response = await Dio().post( url.toString(), data: data, 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, null); 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); } }