import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'package:adguard_home_manager/models/server.dart'; enum ExceptionType { socket, timeout, handshake, http, unknown } class HttpResponse { final bool successful; final String? body; final int? statusCode; final ExceptionType? exception; const HttpResponse({ required this.successful, required this.body, required this.statusCode, this.exception, }); } String getConnectionString({ required Server server, required String urlPath, }) { return "${server.connectionMethod}://${server.domain}${server.port != null ? ':${server.port}' : ""}${server.path ?? ""}/control$urlPath"; } class HttpRequestClient { static Future get({ required String urlPath, required Server server, int timeout = 10, }) async{ final String connectionString = getConnectionString(server: server, urlPath: urlPath); try { HttpClient httpClient = HttpClient(); HttpClientRequest request = await httpClient.getUrl(Uri.parse(connectionString)); if (server.authToken != null) { request.headers.set('Authorization', 'Basic ${server.authToken}'); } HttpClientResponse response = await request.close().timeout( Duration(seconds: timeout) ); String reply = await response.transform(utf8.decoder).join(); httpClient.close(); return HttpResponse( successful: response.statusCode >= 400 ? false : true, body: reply, statusCode: response.statusCode ); } on SocketException { return const HttpResponse( successful: false, body: null, statusCode: null, exception: ExceptionType.socket ); } on TimeoutException { return const HttpResponse( successful: false, body: null, statusCode: null, exception: ExceptionType.timeout ); } on HandshakeException { return const HttpResponse( successful: false, body: null, statusCode: null, exception: ExceptionType.handshake ); } on HttpException { return const HttpResponse( successful: false, body: null, statusCode: null, exception: ExceptionType.http ); } catch (e) { return const HttpResponse( successful: false, body: null, statusCode: null, exception: ExceptionType.unknown ); } } static Future post({ required String urlPath, required Server server, dynamic body, int timeout = 10, }) async{ final String connectionString = getConnectionString(server: server, urlPath: urlPath); try { HttpClient httpClient = HttpClient(); HttpClientRequest request = await httpClient.postUrl(Uri.parse(connectionString)); if (server.authToken != null) { request.headers.set('Authorization', 'Basic ${server.authToken}'); } request.headers.set('content-type', 'application/json'); request.add(utf8.encode(json.encode(body))); HttpClientResponse response = await request.close().timeout( Duration(seconds: timeout) ); String reply = await response.transform(utf8.decoder).join(); httpClient.close(); return HttpResponse( successful: response.statusCode >= 400 ? false : true, body: reply, statusCode: response.statusCode ); } on SocketException { return const HttpResponse( successful: false, body: null, statusCode: null, exception: ExceptionType.socket ); } on TimeoutException { return const HttpResponse( successful: false, body: null, statusCode: null, exception: ExceptionType.timeout ); } on HttpException { return const HttpResponse( successful: false, body: null, statusCode: null, exception: ExceptionType.http ); } on HandshakeException { return const HttpResponse( successful: false, body: null, statusCode: null, exception: ExceptionType.handshake ); } catch (e) { return const HttpResponse( successful: false, body: null, statusCode: null, exception: ExceptionType.unknown ); } } static Future put({ required String urlPath, required Server server, dynamic body, int timeout = 10, }) async{ final String connectionString = getConnectionString(server: server, urlPath: urlPath); try { HttpClient httpClient = HttpClient(); HttpClientRequest request = await httpClient.putUrl(Uri.parse(connectionString)); if (server.authToken != null) { request.headers.set('Authorization', 'Basic ${server.authToken}'); } request.headers.set('content-type', 'application/json'); request.add(utf8.encode(json.encode(body))); HttpClientResponse response = await request.close().timeout( Duration(seconds: timeout) ); String reply = await response.transform(utf8.decoder).join(); httpClient.close(); return HttpResponse( successful: response.statusCode >= 400 ? false : true, body: reply, statusCode: response.statusCode ); } on SocketException { return const HttpResponse( successful: false, body: null, statusCode: null, exception: ExceptionType.socket ); } on TimeoutException { return const HttpResponse( successful: false, body: null, statusCode: null, exception: ExceptionType.timeout ); } on HttpException { return const HttpResponse( successful: false, body: null, statusCode: null, exception: ExceptionType.http ); } on HandshakeException { return const HttpResponse( successful: false, body: null, statusCode: null, exception: ExceptionType.handshake ); } catch (e) { return const HttpResponse( successful: false, body: null, statusCode: null, exception: ExceptionType.unknown ); } } }