2 // HttpClientHandler.cs
5 // Marek Safar <marek.safar@gmail.com>
7 // Copyright (C) 2011 Xamarin Inc (http://www.xamarin.com)
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 using System.Threading;
30 using System.Threading.Tasks;
31 using System.Collections.Specialized;
32 using System.Net.Http.Headers;
34 namespace System.Net.Http
36 public class HttpClientHandler : HttpMessageHandler
38 bool allowAutoRedirect;
39 DecompressionMethods automaticDecompression;
40 CookieContainer cookieContainer;
41 ICredentials credentials;
42 int maxAutomaticRedirections;
43 long maxRequestContentBufferSize;
47 bool useDefaultCredentials;
49 ClientCertificateOption certificate;
51 public HttpClientHandler ()
53 allowAutoRedirect = true;
54 maxAutomaticRedirections = 50;
55 maxRequestContentBufferSize = int.MaxValue;
60 public bool AllowAutoRedirect {
62 return allowAutoRedirect;
65 allowAutoRedirect = value;
69 public DecompressionMethods AutomaticDecompression {
71 return automaticDecompression;
74 automaticDecompression = value;
78 public ClientCertificateOption ClientCertificateOptions {
87 public CookieContainer CookieContainer {
89 return cookieContainer ?? (cookieContainer = new CookieContainer ());
92 cookieContainer = value;
96 public ICredentials Credentials {
105 public int MaxAutomaticRedirections {
107 return maxAutomaticRedirections;
111 throw new ArgumentOutOfRangeException ();
113 maxAutomaticRedirections = value;
117 public long MaxRequestContentBufferSize {
119 return maxRequestContentBufferSize;
123 throw new ArgumentOutOfRangeException ();
125 maxRequestContentBufferSize = value;
129 public bool PreAuthenticate {
131 return preAuthenticate;
134 preAuthenticate = value;
138 public IWebProxy Proxy {
144 throw new InvalidOperationException ();
150 public virtual bool SupportsAutomaticDecompression {
156 public virtual bool SupportsProxy {
162 public virtual bool SupportsRedirectConfiguration {
168 public bool UseCookies {
177 public bool UseDefaultCredentials {
179 return useDefaultCredentials;
182 useDefaultCredentials = value;
186 public bool UseProxy {
195 protected override void Dispose (bool disposing)
198 base.Dispose (disposing);
201 HttpWebRequest CreateWebRequest (HttpRequestMessage request)
203 var wr = new HttpWebRequest (request.RequestUri);
204 wr.ThrowOnError = false;
206 wr.ConnectionGroupName = "HttpClientHandler";
207 wr.Method = request.Method.Method;
208 wr.ProtocolVersion = request.Version;
210 if (wr.ProtocolVersion == HttpVersion.Version10) {
211 wr.KeepAlive = request.Headers.ConnectionKeepAlive;
213 wr.KeepAlive = request.Headers.ConnectionClose != true;
216 wr.ServicePoint.Expect100Continue = request.Headers.ExpectContinue == true;
218 if (allowAutoRedirect) {
219 wr.AllowAutoRedirect = true;
220 wr.MaximumAutomaticRedirections = maxAutomaticRedirections;
223 wr.AutomaticDecompression = automaticDecompression;
224 wr.PreAuthenticate = preAuthenticate;
227 wr.CookieContainer = cookieContainer;
230 if (useDefaultCredentials) {
231 wr.UseDefaultCredentials = true;
233 wr.Credentials = credentials;
240 // Add request headers
241 var headers = wr.Headers;
242 foreach (var header in request.Headers) {
243 foreach (var value in header.Value) {
244 headers.AddValue (header.Key, value);
251 HttpResponseMessage CreateResponseMessage (HttpWebResponse wr, HttpRequestMessage requestMessage)
253 var response = new HttpResponseMessage (wr.StatusCode);
254 response.RequestMessage = requestMessage;
255 response.ReasonPhrase = wr.StatusDescription;
256 response.Content = new StreamContent (wr.GetResponseStream ());
258 var headers = wr.Headers;
259 for (int i = 0; i < headers.Count; ++i) {
260 var key = headers.GetKey(i);
261 var value = headers.GetValues (i);
263 HttpHeaders item_headers;
264 if (HttpHeaders.GetKnownHeaderKind (key) == Headers.HttpHeaderKind.Content)
265 item_headers = response.Content.Headers;
267 item_headers = response.Headers;
269 item_headers.TryAddWithoutValidation (key, value);
275 protected async internal override Task<HttpResponseMessage> SendAsync (HttpRequestMessage request, CancellationToken cancellationToken)
277 var wrequest = CreateWebRequest (request);
279 if (request.Content != null) {
280 var headers = wrequest.Headers;
281 foreach (var header in request.Content.Headers) {
282 foreach (var value in header.Value) {
283 headers.AddValue (header.Key, value);
287 var stream = wrequest.GetRequestStream ();
288 await request.Content.CopyToAsync (stream);
291 // FIXME: GetResponseAsync does not accept cancellationToken
292 var wresponse = (HttpWebResponse) await wrequest.GetResponseAsync ().ConfigureAwait (false);
293 return CreateResponseMessage (wresponse, request);