예제 #1
0
        internal async Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken, bool isFirstRequest)
        {
            sentRequest = true;

            CFHTTPStream stream;

            using (var message = CreateWebRequestAsync(request))
            {
                if (request.Content != null)
                {
                    var data = await request.Content.ReadAsByteArrayAsync().ConfigureAwait(false);

                    message.SetBody(data);
                }

                stream = CFHTTPStream.CreateForHTTPRequest(message);
            }

            if (useSystemProxy)
            {
                var proxies = CF.CFNetwork.GetSystemProxySettings();
                if (proxies.HTTPEnable)
                {
                    stream.SetProxy(proxies);
                }
            }

            if (!isFirstRequest && allowAutoRedirect)
            {
                stream.ShouldAutoredirect = allowAutoRedirect;
            }
            stream.HasBytesAvailableEvent += HandleHasBytesAvailableEvent;
            stream.ErrorEvent             += HandleErrorEvent;
            stream.ClosedEvent            += HandleClosedEvent;

            var response = new TaskCompletionSource <HttpResponseMessage> ();

            if (cancellationToken.IsCancellationRequested)
            {
                response.SetCanceled();
                return(await response.Task);
            }

            var bucket = new StreamBucket()
            {
                Request  = request,
                Response = response,
            };

            streamBuckets.Add(stream.Handle, bucket);

            //
            // Always schedule stream events handling on main-loop. Due to ConfigureAwait (false) we may end up
            // on any thread-pool thread which may not have run-loop running
            //
            stream.EnableEvents(CF.CFRunLoop.Main, CF.CFRunLoop.ModeCommon);

            stream.Open();

            bucket.CancellationTokenRegistration = cancellationToken.Register(() => {
                StreamBucket bucket2;
                if (!streamBuckets.TryGetValue(stream.Handle, out bucket2))
                {
                    return;
                }

                bucket2.Response.TrySetCanceled();
                CloseStream(stream);
            });

            if (isFirstRequest)
            {
                var initialRequest = await response.Task;
                var status         = initialRequest.StatusCode;
                if (IsRedirect(status) && allowAutoRedirect)
                {
                    bucket.StreamCanBeDisposed = true;
                    // we do not care about the first stream cbs
                    stream.HasBytesAvailableEvent -= HandleHasBytesAvailableEvent;
                    stream.ErrorEvent             -= HandleErrorEvent;
                    stream.ClosedEvent            -= HandleClosedEvent;
                    // remove headers in a redirect for Authentication.
                    request.Headers.Authorization = null;
                    return(await SendAsync(request, cancellationToken, false).ConfigureAwait(false));
                }
                return(initialRequest);
            }
            return(await response.Task);
        }
예제 #2
0
        protected internal override async Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            sentRequest = true;

            CFHTTPStream stream;

            using (var message = CreateWebRequestAsync(request))
            {
                if (request.Content != null)
                {
                    var data = await request.Content.ReadAsByteArrayAsync().ConfigureAwait(false);

                    message.SetBody(data);
                }

                stream = CFHTTPStream.CreateForHTTPRequest(message);
            }

            if (useSystemProxy)
            {
                var proxies = CF.CFNetwork.GetSystemProxySettings();
                if (proxies.HTTPEnable)
                {
                    stream.SetProxy(proxies);
                }
            }

            stream.ShouldAutoredirect      = allowAutoRedirect;
            stream.HasBytesAvailableEvent += HandleHasBytesAvailableEvent;
            stream.ErrorEvent             += HandleErrorEvent;
            stream.ClosedEvent            += HandleClosedEvent;

            var response = new TaskCompletionSource <HttpResponseMessage> ();

            if (cancellationToken.IsCancellationRequested)
            {
                response.SetCanceled();
                return(await response.Task);
            }

            var bucket = new StreamBucket()
            {
                Request  = request,
                Response = response,
            };

            streamBuckets.Add(stream.Handle, bucket);

            //
            // Always schedule stream events handling on main-loop. Due to ConfigureAwait (false) we may end up
            // on any thread-pool thread which may not have run-loop running
            //
#if XAMCORE_2_0
            stream.EnableEvents(CF.CFRunLoop.Main, CF.CFRunLoop.ModeCommon);
#else
            stream.EnableEvents(CF.CFRunLoop.Main, CF.CFRunLoop.CFRunLoopCommonModes);
#endif

            stream.Open();

            bucket.CancellationTokenRegistration = cancellationToken.Register(() => {
                StreamBucket bucket2;
                if (!streamBuckets.TryGetValue(stream.Handle, out bucket2))
                {
                    return;
                }

                bucket2.Response.TrySetCanceled();
                CloseStream(stream);
            });

            return(await response.Task);
        }