private async Task <Response> SendInternalAsync(Request request, WebRequestState state, TimeSpan?connectionTimeout, CancellationToken cancellationToken) { CancellationTokenRegistration registration; try { registration = cancellationToken.Register(state.CancelRequest); } catch (ObjectDisposedException) { return(Responses.Canceled); } using (registration) using (state) { if (state.RequestCanceled) { return(Responses.Canceled); } state.Request = WebRequestFactory.Create(request, state.TimeRemaining, Settings, log); HttpActionStatus status; // Step 1: send request body if it was supplied in request. if (state.RequestCanceled) { return(Responses.Canceled); } if (request.HasBody) { status = await connectTimeLimiter .LimitConnectTime(SendRequestBodyAsync(request, state, cancellationToken), request, state, connectionTimeout) .ConfigureAwait(false); if (status != HttpActionStatus.Success) { return(responseFactory.BuildFailureResponse(status, state)); } } // Step 2: receive response from server. if (state.RequestCanceled) { return(Responses.Canceled); } status = request.HasBody ? await GetResponseAsync(request, state).ConfigureAwait(false) : await connectTimeLimiter.LimitConnectTime(GetResponseAsync(request, state), request, state, connectionTimeout).ConfigureAwait(false); if (status != HttpActionStatus.Success) { return(responseFactory.BuildFailureResponse(status, state)); } // Step 3 - download request body if it exists. if (!NeedToReadResponseBody(request, state)) { return(responseFactory.BuildSuccessResponse(state)); } if (ResponseBodyIsTooLarge(state)) { state.CancelRequestAttempt(); return(responseFactory.BuildResponse(ResponseCode.InsufficientStorage, state)); } if (state.RequestCanceled) { return(Responses.Canceled); } if (NeedToStreamResponseBody(state)) { state.ReturnStreamDirectly = true; state.PreventNextDispose(); return(responseFactory.BuildSuccessResponse(state)); } status = await ReadResponseBodyAsync(request, state, cancellationToken) .ConfigureAwait(false); return(status == HttpActionStatus.Success ? responseFactory.BuildSuccessResponse(state) : responseFactory.BuildFailureResponse(status, state)); } }