245 lines
7.7 KiB
Dart
245 lines
7.7 KiB
Dart
import 'dart:convert';
|
|
import 'dart:io';
|
|
import 'package:http/http.dart';
|
|
import 'package:http/io_client.dart';
|
|
import 'package:flutter/foundation.dart';
|
|
|
|
// Combined Riderlog providers:
|
|
|
|
/// Hardcoded known-good IPs for hosts where carrier DNS returns broken nodes.
|
|
/// Confirmed by Python test: 66.116.225.226 = 200 OK, 125.21.240.67 = 404.
|
|
const _knownGoodIPs = <String, String>{
|
|
'queue.workolik.com': '66.116.225.226',
|
|
};
|
|
|
|
/// Creates an IOClient that:
|
|
/// 1. Bypasses SSL certificate errors
|
|
/// 2. Forces known-good IPs for hosts where carrier DNS returns broken CDN nodes
|
|
/// 3. Manually does TLS upgrade with correct SNI (hostname, not IP)
|
|
IOClient _buildSslBypassClient() {
|
|
final httpClient = HttpClient()
|
|
..badCertificateCallback =
|
|
(X509Certificate cert, String host, int port) => true;
|
|
|
|
httpClient.connectionFactory =
|
|
(Uri uri, String? proxyHost, int? proxyPort) async {
|
|
final host = uri.host;
|
|
final port = uri.port;
|
|
|
|
// Use known-good IP if available, else resolve normally (prefer IPv4)
|
|
InternetAddress? target;
|
|
final knownIP = _knownGoodIPs[host];
|
|
if (knownIP != null) {
|
|
target = InternetAddress(knownIP);
|
|
debugPrint('[SSL_CLIENT] Using known-good IP: $knownIP for $host');
|
|
} else {
|
|
try {
|
|
final addresses = await InternetAddress.lookup(
|
|
host,
|
|
type: InternetAddressType.IPv4,
|
|
);
|
|
if (addresses.isNotEmpty) target = addresses.first;
|
|
} catch (_) {}
|
|
}
|
|
|
|
if (uri.scheme == 'https') {
|
|
final socketFuture =
|
|
Socket.connect(target ?? InternetAddress(host), port)
|
|
.then((plain) => SecureSocket.secure(
|
|
plain,
|
|
host: host, // SNI = original hostname for Nginx routing
|
|
onBadCertificate: (_) => true,
|
|
supportedProtocols: ['http/1.1'],
|
|
))
|
|
.then((s) => s as Socket);
|
|
return ConnectionTask.fromSocket<Socket>(socketFuture, () {});
|
|
}
|
|
|
|
return Socket.startConnect(target ?? InternetAddress(host), port);
|
|
};
|
|
|
|
return IOClient(httpClient);
|
|
}
|
|
|
|
|
|
class CreateRiderLogProvider {
|
|
Future<Map<String, dynamic>?> createRiderLog(
|
|
String urldata,
|
|
Map<String, dynamic> data,
|
|
) async {
|
|
const maxAttempts = 3;
|
|
try {
|
|
debugPrint('createRiderLog payload ${json.encode(data)}');
|
|
} catch (_) {}
|
|
|
|
for (int attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
final client = _buildSslBypassClient();
|
|
try {
|
|
final url = Uri.parse(urldata);
|
|
final response = await client.post(
|
|
url,
|
|
body: json.encode(data),
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'Accept': 'application/json',
|
|
},
|
|
);
|
|
debugPrint('createRiderLog url $urldata (attempt $attempt)');
|
|
debugPrint('createRiderLog status ${response.statusCode}');
|
|
debugPrint('createRiderLog response ${response.body}');
|
|
|
|
if (response.statusCode >= 200 && response.statusCode < 300) {
|
|
return json.decode(response.body.toString()) as Map<String, dynamic>;
|
|
} else {
|
|
debugPrint(
|
|
'createRiderLog failed: HTTP ${response.statusCode} (attempt $attempt/$maxAttempts)',
|
|
);
|
|
// On 404/5xx, wait and retry to potentially hit a different CDN node
|
|
if (attempt < maxAttempts) {
|
|
await Future.delayed(const Duration(seconds: 1));
|
|
}
|
|
}
|
|
} catch (e) {
|
|
debugPrint('createRiderLog exception (attempt $attempt): $e');
|
|
if (attempt < maxAttempts) {
|
|
await Future.delayed(const Duration(seconds: 1));
|
|
}
|
|
} finally {
|
|
client.close();
|
|
}
|
|
}
|
|
|
|
debugPrint('createRiderLog failed after $maxAttempts attempts');
|
|
return null;
|
|
}
|
|
}
|
|
|
|
|
|
class UpdateRiderLogProvider {
|
|
Future<Map<String, dynamic>?> updateRiderLog(
|
|
String urldata,
|
|
Map<String, dynamic> data,
|
|
) async {
|
|
try {
|
|
final url = Uri.parse(urldata);
|
|
final response = await put(
|
|
url,
|
|
body: json.encode(data),
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'Accept': 'application/json',
|
|
},
|
|
);
|
|
|
|
debugPrint('updateRiderLog url: $urldata');
|
|
debugPrint('updateRiderLog response: ${response.body}');
|
|
|
|
if (response.statusCode >= 200 && response.statusCode < 300) {
|
|
final decoded = json.decode(response.body);
|
|
if (decoded is Map<String, dynamic>) {
|
|
return decoded;
|
|
} else {
|
|
debugPrint('⚠️ updateRiderLog: Expected Map but got ${decoded.runtimeType}');
|
|
return {};
|
|
}
|
|
} else {
|
|
debugPrint('❌ updateRiderLog failed with code ${response.statusCode}');
|
|
return {};
|
|
}
|
|
} catch (e) {
|
|
debugPrint('❌ Exception in updateRiderLog: $e');
|
|
return {};
|
|
}
|
|
}
|
|
}
|
|
|
|
class GetRiderLogProvider {
|
|
Future<Map<String, dynamic>?> getRiderLog(String urldata) async {
|
|
Map<String, dynamic>? getRiderLogResponse;
|
|
try {
|
|
final url = Uri.parse(urldata);
|
|
final response = await get(url, headers: {
|
|
'Content-Type': 'application/json',
|
|
'Accept': 'application/json',
|
|
});
|
|
debugPrint('getRiderLog response ${response.body}');
|
|
debugPrint('getRiderLog url ${urldata.toString()}');
|
|
getRiderLogResponse =
|
|
json.decode(response.body.toString()) as Map<String, dynamic>;
|
|
} catch (e) {
|
|
debugPrint(e.toString());
|
|
}
|
|
return getRiderLogResponse;
|
|
}
|
|
|
|
Future<Map<String, dynamic>?> getRiderCount(String urldata) async {
|
|
Map<String, dynamic>? getRiderCountResponse;
|
|
try {
|
|
final url = Uri.parse(urldata);
|
|
final response = await get(url, headers: {
|
|
'Content-Type': 'application/json',
|
|
'Accept': 'application/json',
|
|
});
|
|
debugPrint('getRiderCount response ${response.body}');
|
|
debugPrint('getRiderCount url ${urldata.toString()}');
|
|
getRiderCountResponse =
|
|
json.decode(response.body.toString()) as Map<String, dynamic>;
|
|
} catch (e) {
|
|
debugPrint(e.toString());
|
|
}
|
|
return getRiderCountResponse;
|
|
}
|
|
}
|
|
|
|
class BreakRiderLogProvider {
|
|
Future<Map<String, dynamic>?> createBreakRiderLog(
|
|
String urldata,
|
|
Map<String, dynamic> data,
|
|
) async {
|
|
Map<String, dynamic>? breakLogResponse;
|
|
try {
|
|
final url = Uri.parse(urldata);
|
|
final response = await post(
|
|
url,
|
|
body: json.encode(data),
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'Accept': 'application/json',
|
|
},
|
|
);
|
|
debugPrint('createBreakRiderLog url $urldata');
|
|
debugPrint('createBreakRiderLog response ${response.body}');
|
|
breakLogResponse =
|
|
json.decode(response.body.toString()) as Map<String, dynamic>;
|
|
} catch (e) {
|
|
debugPrint(e.toString());
|
|
}
|
|
return breakLogResponse;
|
|
}
|
|
|
|
Future<Map<String, dynamic>?> updateBreakRiderLog(
|
|
String urldata,
|
|
Map<String, dynamic> data,
|
|
) async {
|
|
Map<String, dynamic>? breakLogResponse;
|
|
try {
|
|
final url = Uri.parse(urldata);
|
|
final response = await put(
|
|
url,
|
|
body: json.encode(data),
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'Accept': 'application/json',
|
|
},
|
|
);
|
|
debugPrint('updateBreakRiderLog url $urldata');
|
|
debugPrint('updateBreakRiderLog response ${response.body}');
|
|
breakLogResponse =
|
|
json.decode(response.body.toString()) as Map<String, dynamic>;
|
|
} catch (e) {
|
|
debugPrint(e.toString());
|
|
}
|
|
return breakLogResponse;
|
|
}
|
|
}
|