/// <summary>
        /// Asynchronously send a request
        /// </summary>
        /// <param name="request">The request do send</param>
        /// <param name="cancellationToken">The cancellation token used to signal an abortion</param>
        /// <returns>The task to query the response</returns>
        public async Task<IHttpResponseMessage> SendAsync(IHttpRequestMessage request, CancellationToken cancellationToken)
        {
            var uri = new Uri(BaseAddress, request.RequestUri);
            var wr = _httpClientFactory.CreateWebRequest(uri);
            if (wr.SupportsCookieContainer && CookieContainer != null)
                wr.CookieContainer = CookieContainer;
            if (Credentials != null)
                wr.Credentials = Credentials;
            wr.Method = request.Method.ToString();
#if !PCL
            wr.Proxy = Proxy ?? System.Net.WebRequest.DefaultWebProxy;
#endif

            // Combine all headers into one header collection
            var headers = new GenericHttpHeaders();

            if (request.Content?.Headers != null)
            {
                foreach (var header in request.Content.Headers.Where(x => !headers.Contains(x.Key)))
                {
                    headers.TryAddWithoutValidation(header.Key, header.Value);
                }
            }

            if (request.Headers != null)
            {
                foreach (var header in request.Headers.Where(x => !headers.Contains(x.Key)))
                {
                    headers.TryAddWithoutValidation(header.Key, header.Value);
                }
            }

            if (DefaultRequestHeaders != null)
            {
                foreach (var header in DefaultRequestHeaders.Where(x => !headers.Contains(x.Key)))
                {
                    headers.TryAddWithoutValidation(header.Key, header.Value);
                }
            }

            bool hasContentLength = false;
            foreach (var header in headers)
            {
                var value = string.Join(",", header.Value);
                SetWebRequestHeaderValue(wr, header.Key, value);
                if (!hasContentLength && string.Equals(header.Key, "content-length", StringComparison.OrdinalIgnoreCase))
                    hasContentLength = true;
            }

            if (request.Content != null)
            {
                // Add content length if not provided by the user.
                if (!hasContentLength)
                {
                    long contentLength;
                    if (request.Content.TryComputeLength(out contentLength))
                    {
#if PCL || NETFX_CORE || WINDOWS_STORE
                        wr.Headers[HttpRequestHeader.ContentLength] = contentLength.ToString();
#else
                        wr.ContentLength = contentLength;
#endif
                    }
                }

                try
                {
#if PCL && ASYNC_PCL
                    var getRequestStreamAsync = Task.Factory.FromAsync<Stream>(wr.BeginGetRequestStream, wr.EndGetRequestStream, null);
                    var requestStream = await getRequestStreamAsync.HandleCancellation(cancellationToken);
#else
                    var requestStream = await wr.GetRequestStreamAsync().HandleCancellation(cancellationToken);
#endif
                    using (requestStream)
                    {
                        var temp = new MemoryStream();
                        await request.Content.CopyToAsync(temp);
                        var buffer = temp.ToArray();
                        await requestStream.WriteAsync(buffer, 0, buffer.Length, cancellationToken);
                        await requestStream.FlushAsync(cancellationToken);
                    }
                }
                catch (OperationCanceledException)
                {
                    wr.Abort();
                    throw;
                }
            }

            try
            {
#if PCL && ASYNC_PCL
                var getResponseAsync = Task.Factory.FromAsync<WebResponse>(wr.BeginGetResponse, wr.EndGetResponse, null);
                var response = await getResponseAsync.HandleCancellation(cancellationToken);
#else
                var response = await wr.GetResponseAsync().HandleCancellation(cancellationToken);
#endif
                var httpWebResponse = response as HttpWebResponse;
                if (httpWebResponse == null)
                {
                    response.Dispose();
                    throw new ProtocolViolationException("No HTTP request")
                        {
                            Data =
                                {
                                    { "URI", wr.RequestUri },
                                },
                        };
                }

                return new DefaultHttpResponseMessage(request, httpWebResponse);
            }
            catch (WebException ex)
            {
                var httpWebResponse = (HttpWebResponse)ex.Response;
                return new DefaultHttpResponseMessage(request, httpWebResponse, ex);
            }
            catch (OperationCanceledException)
            {
                wr.Abort();
                throw;
            }
        }