import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:socks5_proxy/socks_client.dart'; import '../utilities/logger.dart'; // WIP wrapper layer // TODO expand this class class Response { final int code; final List bodyBytes; String get body => utf8.decode(bodyBytes, allowMalformed: true); Response(this.bodyBytes, this.code); } class HTTP { Future get({ required Uri url, Map? headers, required ({ InternetAddress host, int port, })? proxyInfo, }) async { final httpClient = HttpClient(); try { if (proxyInfo != null) { SocksTCPClient.assignToHttpClient(httpClient, [ ProxySettings( proxyInfo.host, proxyInfo.port, ), ]); } final HttpClientRequest request = await httpClient.getUrl( url, ); if (headers != null) { headers.forEach((key, value) => request.headers.add(key, value)); } final response = await request.close(); return Response( await _bodyBytes(response), response.statusCode, ); } catch (e, s) { Logging.instance.log( "HTTP.get() rethrew: $e\n$s", level: LogLevel.Info, ); rethrow; } finally { httpClient.close(force: true); } } Future post({ required Uri url, Map? headers, Object? body, Encoding? encoding, required ({ InternetAddress host, int port, })? proxyInfo, }) async { final httpClient = HttpClient(); try { if (proxyInfo != null) { SocksTCPClient.assignToHttpClient(httpClient, [ ProxySettings( proxyInfo.host, proxyInfo.port, ), ]); } final HttpClientRequest request = await httpClient.postUrl( url, ); if (headers != null) { headers.forEach((key, value) => request.headers.add(key, value)); } request.write(body); final response = await request.close(); return Response( await _bodyBytes(response), response.statusCode, ); } catch (e, s) { Logging.instance.log( "HTTP.post() rethrew: $e\n$s", level: LogLevel.Info, ); rethrow; } finally { httpClient.close(force: true); } } Future _bodyBytes(HttpClientResponse response) { final completer = Completer(); final List bytes = []; response.listen( (data) { bytes.addAll(data); }, onDone: () => completer.complete( Uint8List.fromList(bytes), ), onError: (Object err, StackTrace s) => Logging.instance.log( "Http wrapper layer listen: $err\n$s", level: LogLevel.Error, ), ); return completer.future; } }