send method
Sends an HTTP request and asynchronously returns the response.
Implementation
@override
Future<StreamedResponse> send(BaseRequest originalRequest) async {
final request = $HandleFeatures.disableAsyncDeserializationWithHandle
? markHandleUsageInRequestHeaders(originalRequest)
: originalRequest;
int retryCount = 0;
BaseRequest latestRequest = request;
StreamedResponse? response;
StreamController<List<int>>? sendBodyStreamController;
StreamController<List<int>>? retryBodyStreamController;
StreamSubscription<List<int>>? bodyStreamSubscription;
FutureOr<void> disposeLatest() {
bodyStreamSubscription?.cancel();
sendBodyStreamController?.close();
retryBodyStreamController?.close();
bodyStreamSubscription = null;
sendBodyStreamController = null;
retryBodyStreamController = null;
}
do {
try {
disposeLatest();
final FinalizedBodyStream body = latestRequest.finalizedBodyStream;
sendBodyStreamController = StreamController<List<int>>();
retryBodyStreamController = StreamController<List<int>>();
bodyStreamSubscription = body.addStreamToSinks([
sendBodyStreamController!.sink,
retryBodyStreamController!.sink,
]);
try {
response = await inner.send(
latestRequest.createCopy(sendBodyStreamController!.stream),
);
if (!await retryRequestWhen(response, retryCount)) {
return response;
}
unawaitedResponse(response);
} catch (e, s) {
if (!await retryRequestWhenError(e, s, retryCount)) rethrow;
}
final delay = calculateDelay(retryCount);
if (delay != null) {
await Future.delayed(delay);
}
bool didConsumeBodyInCopiedRequest = false;
FinalizedBodyStream getBodyStream() {
didConsumeBodyInCopiedRequest = true;
return retryBodyStreamController!.stream;
}
latestRequest = await getUpdatedRequest(
request,
latestRequest,
getBodyStream,
response,
retryCount,
);
if (didConsumeBodyInCopiedRequest) {
retryBodyStreamController!.close();
}
await onRequestRetry(latestRequest, response, retryCount);
} on ClientException {
disposeLatest();
rethrow;
} catch (e, s) {
disposeLatest();
throw HandleException(
'Unexpected exception while retrying a request',
uri: request.url,
statusCode: response?.statusCode,
innerException: e,
innerStackTrace: s,
);
}
retryCount++;
} while (retryCount < HANDLE_RETRY_MAX_LIMIT);
disposeLatest();
throw HandleRetryLimitExceededException(
'Too many retries',
retryCount,
uri: request.url,
statusCode: response?.statusCode,
);
}