send method
Sends an HTTP request and asynchronously returns the response.
Implementers should call BaseRequest.finalize to get the body of the
request as a ByteStream. They shouldn't make any assumptions about the
state of the stream; it could have data written to it asynchronously at a
later point, or it could already be closed when it's returned. Any
internal HTTP errors should be wrapped as ClientExceptions.
Implementation
@override
Future<http.StreamedResponse> send(http.BaseRequest request) async {
if (_rotateProxies || _currentProxy == null) {
try {
_currentProxy = _proxyManager.getNextProxy(
validated: _useValidatedProxies,
);
} catch (e) {
// If no proxies are available, try to fetch some
try {
if (_useValidatedProxies) {
await _proxyManager.fetchValidatedProxies();
} else {
await _proxyManager.fetchProxies();
}
_currentProxy = _proxyManager.getNextProxy(
validated: _useValidatedProxies,
);
} catch (_) {
// If still no proxies, use direct connection
return _inner.send(request);
}
}
}
// Set up the proxy
final proxy = _currentProxy!;
final proxyUrl = '${proxy.ip}:${proxy.port}';
// Create a new HttpClient with the proxy
final httpClient = HttpClient();
httpClient.findProxy = (uri) => 'PROXY $proxyUrl';
// Set up authentication if needed
if (proxy.isAuthenticated) {
httpClient.authenticate = (Uri url, String scheme, String? realm) {
httpClient.addCredentials(
url,
realm ?? '',
HttpClientBasicCredentials(proxy.username!, proxy.password!),
);
return Future.value(true);
};
}
// Convert the request to an HttpClientRequest
final url = request.url;
final httpRequest = await httpClient.openUrl(request.method, url);
// Copy headers
request.headers.forEach((name, value) {
httpRequest.headers.set(name, value);
});
// Copy the body
if (request is http.Request) {
httpRequest.write(request.body);
}
// Send the request
final httpResponse = await httpRequest.close();
// Convert the response to a StreamedResponse
final headers = <String, String>{};
httpResponse.headers.forEach((name, values) {
headers[name] = values.join(',');
});
final response = http.StreamedResponse(
httpResponse,
httpResponse.statusCode,
contentLength: httpResponse.contentLength,
request: request,
headers: headers,
isRedirect: httpResponse.isRedirect,
persistentConnection: httpResponse.persistentConnection,
reasonPhrase: httpResponse.reasonPhrase,
);
// Close the client
httpClient.close();
return response;
}