public static WebResponseStream Create(CFHTTPMessage request, WebRequestStream body) { var stream = CFStream.CreateForStreamedHTTPRequest(request, body.ReadStream); if (stream == null) { return(null); } return(new WebResponseStream(stream, body)); }
async Task <HttpResponseMessage> ProcessRequest(HttpRequestMessage request, CFHTTPMessage message, WebRequestStream body, bool retryWithCredentials, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); WebResponseStream stream; if (body != null) { stream = WebResponseStream.Create(message, body); } else { stream = WebResponseStream.Create(message); } if (stream == null) { throw new HttpRequestException(string.Format( "Failed to create web request for '{0}'.", request.RequestUri) ); } stream.Stream.ShouldAutoredirect = AllowAutoRedirect; stream.Stream.AttemptPersistentConnection = GetKeepAlive(request); var response = await stream.Open( WorkerThread, cancellationToken).ConfigureAwait(false); var status = (HttpStatusCode)response.ResponseStatusCode; if (retryWithCredentials && (body == null) && (status == HttpStatusCode.Unauthorized) || (status == HttpStatusCode.ProxyAuthenticationRequired)) { if (HandleAuthentication(request.RequestUri, message, response)) { stream.Dispose(); return(await ProcessRequest( request, message, null, false, cancellationToken)); } } // The Content object takes ownership of the stream, so we don't // dispose it here. var retval = new HttpResponseMessage(); retval.StatusCode = response.ResponseStatusCode; retval.ReasonPhrase = GetReasonPhrase(response); retval.Version = response.Version; var content = new Content(stream); retval.Content = content; DecodeHeaders(response, retval, content); return(retval); }
WebResponseStream(CFHTTPStream stream, WebRequestStream body) { this.stream = stream; this.body = body; syncRoot = new object(); }
async Task <HttpResponseMessage> ProcessRequest(HttpRequestMessage request, CFHTTPMessage message, WebRequestStream body, bool retryWithCredentials, CancellationToken cancellationToken, bool isFirstRequest) { cancellationToken.ThrowIfCancellationRequested(); WebResponseStream stream; if (body != null) { stream = WebResponseStream.Create(message, body); } else { stream = WebResponseStream.Create(message); } if (stream == null) { throw new HttpRequestException(string.Format( "Failed to create web request for '{0}'.", request.RequestUri) ); } if (!isFirstRequest) { stream.Stream.ShouldAutoredirect = AllowAutoRedirect; } stream.Stream.AttemptPersistentConnection = GetKeepAlive(request); var response = await stream.Open( WorkerThread, cancellationToken).ConfigureAwait(true); // with false, we will have a deadlock. var status = (HttpStatusCode)response.ResponseStatusCode; if (IsRedirect(status)) { request.Headers.Authorization = null; stream.Dispose(); // we cannot reuse the message, will deadlock and also the message.ApplyCredentials (auth, credential); // was called the first time using (var retryMsg = CreateRequest(request, false)) { return(await ProcessRequest( request, retryMsg, null, false, cancellationToken, false)); } } if (retryWithCredentials && (body == null) && (status == HttpStatusCode.Unauthorized) || (status == HttpStatusCode.ProxyAuthenticationRequired)) { if (HandleAuthentication(request.RequestUri, message, response)) { stream.Dispose(); using (var retryMsg = CreateRequest(request, true)) { // behave as if it was the first attempt return(await ProcessRequest( request, message, null, false, cancellationToken, true)); // behave as if it was the first attempt } } } // The Content object takes ownership of the stream, so we don't // dispose it here. var retval = new HttpResponseMessage(); retval.StatusCode = response.ResponseStatusCode; retval.ReasonPhrase = GetReasonPhrase(response); retval.Version = response.Version; var content = new Content(stream); retval.Content = content; DecodeHeaders(response, retval, content); return(retval); }