2023-09-08 20:41:39 +00:00
|
|
|
import 'dart:async';
|
2023-04-27 22:35:16 +00:00
|
|
|
import 'dart:convert';
|
2023-08-07 15:18:08 +00:00
|
|
|
import 'dart:io';
|
2023-04-27 22:35:16 +00:00
|
|
|
|
2023-09-08 18:32:04 +00:00
|
|
|
import 'package:flutter/foundation.dart';
|
2023-08-07 16:46:34 +00:00
|
|
|
import 'package:socks5_proxy/socks_client.dart';
|
2024-10-01 18:30:14 +00:00
|
|
|
|
2024-05-23 00:37:06 +00:00
|
|
|
import '../utilities/logger.dart';
|
2023-04-27 22:35:16 +00:00
|
|
|
|
|
|
|
// WIP wrapper layer
|
|
|
|
|
2023-09-08 15:18:55 +00:00
|
|
|
// TODO expand this class
|
|
|
|
class Response {
|
|
|
|
final int code;
|
2023-09-08 20:41:39 +00:00
|
|
|
final List<int> bodyBytes;
|
2023-09-08 15:18:55 +00:00
|
|
|
|
2023-09-08 20:41:39 +00:00
|
|
|
String get body => utf8.decode(bodyBytes, allowMalformed: true);
|
|
|
|
|
|
|
|
Response(this.bodyBytes, this.code);
|
2023-09-08 15:18:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
class HTTP {
|
|
|
|
Future<Response> get({
|
2023-04-27 22:35:16 +00:00
|
|
|
required Uri url,
|
|
|
|
Map<String, String>? headers,
|
2023-09-08 20:41:39 +00:00
|
|
|
required ({
|
|
|
|
InternetAddress host,
|
|
|
|
int port,
|
|
|
|
})? proxyInfo,
|
2023-04-27 22:35:16 +00:00
|
|
|
}) async {
|
2023-08-07 15:18:08 +00:00
|
|
|
final httpClient = HttpClient();
|
|
|
|
try {
|
2023-09-08 20:41:39 +00:00
|
|
|
if (proxyInfo != null) {
|
2023-08-07 16:46:34 +00:00
|
|
|
SocksTCPClient.assignToHttpClient(httpClient, [
|
|
|
|
ProxySettings(
|
2023-09-08 20:41:39 +00:00
|
|
|
proxyInfo.host,
|
|
|
|
proxyInfo.port,
|
2023-08-07 16:46:34 +00:00
|
|
|
),
|
|
|
|
]);
|
|
|
|
}
|
|
|
|
final HttpClientRequest request = await httpClient.getUrl(
|
|
|
|
url,
|
|
|
|
);
|
2023-08-07 15:18:08 +00:00
|
|
|
|
2023-08-07 16:46:34 +00:00
|
|
|
if (headers != null) {
|
2023-09-13 21:49:04 +00:00
|
|
|
headers.forEach((key, value) => request.headers.add(key, value));
|
2023-08-07 15:18:08 +00:00
|
|
|
}
|
2023-08-07 16:46:34 +00:00
|
|
|
|
2023-09-08 15:18:55 +00:00
|
|
|
final response = await request.close();
|
2023-09-08 20:41:39 +00:00
|
|
|
|
2023-09-08 15:18:55 +00:00
|
|
|
return Response(
|
2023-09-08 20:41:39 +00:00
|
|
|
await _bodyBytes(response),
|
2023-09-08 15:18:55 +00:00
|
|
|
response.statusCode,
|
|
|
|
);
|
2023-08-07 15:18:08 +00:00
|
|
|
} catch (e, s) {
|
|
|
|
Logging.instance.log(
|
|
|
|
"HTTP.get() rethrew: $e\n$s",
|
|
|
|
level: LogLevel.Info,
|
|
|
|
);
|
|
|
|
rethrow;
|
|
|
|
} finally {
|
|
|
|
httpClient.close(force: true);
|
2023-04-27 22:35:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-08 15:18:55 +00:00
|
|
|
Future<Response> post({
|
2023-04-27 22:35:16 +00:00
|
|
|
required Uri url,
|
|
|
|
Map<String, String>? headers,
|
|
|
|
Object? body,
|
|
|
|
Encoding? encoding,
|
2023-09-08 20:41:39 +00:00
|
|
|
required ({
|
|
|
|
InternetAddress host,
|
|
|
|
int port,
|
|
|
|
})? proxyInfo,
|
2023-04-27 22:35:16 +00:00
|
|
|
}) async {
|
2023-08-07 15:18:08 +00:00
|
|
|
final httpClient = HttpClient();
|
|
|
|
try {
|
2023-09-08 20:41:39 +00:00
|
|
|
if (proxyInfo != null) {
|
2023-08-07 17:19:09 +00:00
|
|
|
SocksTCPClient.assignToHttpClient(httpClient, [
|
|
|
|
ProxySettings(
|
2023-09-08 20:41:39 +00:00
|
|
|
proxyInfo.host,
|
|
|
|
proxyInfo.port,
|
2023-08-07 17:19:09 +00:00
|
|
|
),
|
|
|
|
]);
|
2023-08-07 16:46:34 +00:00
|
|
|
}
|
|
|
|
final HttpClientRequest request = await httpClient.postUrl(
|
|
|
|
url,
|
|
|
|
);
|
2023-08-07 15:18:08 +00:00
|
|
|
|
2023-08-07 16:46:34 +00:00
|
|
|
if (headers != null) {
|
2023-09-13 21:49:04 +00:00
|
|
|
headers.forEach((key, value) => request.headers.add(key, value));
|
2023-08-07 15:18:08 +00:00
|
|
|
}
|
2023-08-07 16:46:34 +00:00
|
|
|
|
|
|
|
request.write(body);
|
|
|
|
|
2023-09-08 15:18:55 +00:00
|
|
|
final response = await request.close();
|
|
|
|
return Response(
|
2023-09-08 20:41:39 +00:00
|
|
|
await _bodyBytes(response),
|
2023-09-08 15:18:55 +00:00
|
|
|
response.statusCode,
|
|
|
|
);
|
2023-08-07 15:18:08 +00:00
|
|
|
} catch (e, s) {
|
|
|
|
Logging.instance.log(
|
|
|
|
"HTTP.post() rethrew: $e\n$s",
|
|
|
|
level: LogLevel.Info,
|
2023-04-27 22:35:16 +00:00
|
|
|
);
|
2023-08-07 15:18:08 +00:00
|
|
|
rethrow;
|
|
|
|
} finally {
|
|
|
|
httpClient.close(force: true);
|
2023-04-27 22:35:16 +00:00
|
|
|
}
|
|
|
|
}
|
2023-09-08 20:41:39 +00:00
|
|
|
|
|
|
|
Future<Uint8List> _bodyBytes(HttpClientResponse response) {
|
|
|
|
final completer = Completer<Uint8List>();
|
|
|
|
final List<int> bytes = [];
|
|
|
|
response.listen(
|
|
|
|
(data) {
|
|
|
|
bytes.addAll(data);
|
|
|
|
},
|
|
|
|
onDone: () => completer.complete(
|
|
|
|
Uint8List.fromList(bytes),
|
|
|
|
),
|
2024-10-01 18:30:14 +00:00
|
|
|
onError: (Object err, StackTrace s) => Logging.instance.log(
|
|
|
|
"Http wrapper layer listen: $err\n$s",
|
|
|
|
level: LogLevel.Error,
|
|
|
|
),
|
2023-09-08 20:41:39 +00:00
|
|
|
);
|
|
|
|
return completer.future;
|
|
|
|
}
|
2023-04-27 22:35:16 +00:00
|
|
|
}
|