/// <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; } }