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();
 }
Example #4
0
        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);
        }