httpRequest method
Sends an HTTP request with certificate pinning support.
This method performs an HTTP request using the specified method and url,
with optional body, headers, and encoding. The request is secured using
the provided certificateHash for certificate pinning.
On both Android and iOS, the request is performed via FFI in a separate Isolate using compute() to prevent UI blocking. This provides better performance than MethodChannel as there's no serialization overhead.
Throws an ArgumentError if body is not a String or Map.
Throws an UnsupportedError if the platform is not Android or iOS.
Returns the parsed response as a String.
Parameters:
method: The HTTP method to use (e.g., 'GET', 'POST').url: The URL to send the request to.body: The request body, as aStringorMap. Optional.headers: The HTTP headers as a map of key-value pairs. Optional.encoding: The encoding type for the request body (default is 'json'). Optional.certificateHash: The hash of the certificate to pin against.pinningMethod: The pinning method to use (certificate or publickey).
Implementation
Future<String> httpRequest({
required String method,
required String url,
Object? body,
Map<String, String>? headers,
String? encoding,
required String certificateHash,
required PinningMethod pinningMethod,
}) async {
final String bodyStr;
if (body == null) {
bodyStr = '';
} else if (body is String) {
bodyStr = body;
} else if (body is Map) {
bodyStr = jsonEncode(body);
} else {
throw ArgumentError('Body must be a String or Map');
}
final String headersStr = headers == null ? '' : jsonEncode(headers);
final params = _FFIRequestParams(
method: method,
url: url,
bodyStr: bodyStr,
headersStr: headersStr,
encoding: encoding ?? 'json',
certificateHash: certificateHash,
pinningMethod: pinningMethod.value,
);
if (Platform.isAndroid) {
// ASYNCHRONOUS FFI SOLUTION: Use compute() to execute FFI in separate Isolate
// This solves the UI blocking problem on Android
// compute() executes _executeFFIInIsolateAndroid in a separate Isolate
// ensuring the UI never blocks
return await compute(_executeFFIInIsolateAndroid, params);
} else if (Platform.isIOS) {
// iOS FFI SOLUTION: Use compute() to execute FFI in separate Isolate
// This provides better performance than MethodChannel as there's no
// serialization/deserialization overhead
return await compute(_executeFFIInIsolateIOS, params);
} else {
throw UnsupportedError(
'Unsupported platform \'${Platform.operatingSystem}\'',
);
}
}