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.Net.Http.Headers;
31 using System.Threading.Tasks;
33 namespace System.Net.Http
35 public class HttpClient : IDisposable
37 static readonly TimeSpan TimeoutDefault = TimeSpan.FromSeconds (100);
40 CancellationTokenSource cancellation_token;
42 readonly HttpMessageHandler handler;
43 HttpRequestHeaders headers;
52 public HttpClient (HttpMessageHandler handler)
54 this.handler = handler ?? new HttpClientHandler ();
55 buffer_size = 0x10000;
56 timeout = TimeoutDefault;
59 public Uri BaseAddress {
68 public HttpRequestHeaders DefaultRequestHeaders {
70 return headers ?? (headers = new HttpRequestHeaders ());
74 public int MaxResponseContentBufferSize {
80 throw new ArgumentOutOfRangeException ();
86 public TimeSpan Timeout {
91 if (value != System.Threading.Timeout.InfiniteTimeSpan && value < TimeSpan.Zero)
92 throw new ArgumentOutOfRangeException ();
98 public void CancelPendingRequests ()
100 if (cancellation_token != null)
101 cancellation_token.Cancel ();
103 cancellation_token = new CancellationTokenSource ();
106 public void Dispose ()
111 protected virtual void Dispose (bool disposing)
113 if (disposing && !disposed) {
116 if (cancellation_token != null)
117 cancellation_token.Dispose ();
121 public Task<HttpResponseMessage> DeleteAsync (string requestUri)
123 return SendAsync (new HttpRequestMessage (HttpMethod.Delete, requestUri));
126 public Task<HttpResponseMessage> DeleteAsync (string requestUri, CancellationToken cancellationToken)
128 return SendAsync (new HttpRequestMessage (HttpMethod.Delete, requestUri), cancellationToken);
131 public Task<HttpResponseMessage> DeleteAsync (Uri requestUri)
133 return SendAsync (new HttpRequestMessage (HttpMethod.Delete, requestUri));
136 public Task<HttpResponseMessage> DeleteAsync (Uri requestUri, CancellationToken cancellationToken)
138 return SendAsync (new HttpRequestMessage (HttpMethod.Delete, requestUri), cancellationToken);
141 public Task<HttpResponseMessage> GetAsync (string requestUri)
143 return SendAsync (new HttpRequestMessage (HttpMethod.Get, requestUri));
146 public Task<HttpResponseMessage> GetAsync (string requestUri, CancellationToken cancellationToken)
148 return SendAsync (new HttpRequestMessage (HttpMethod.Get, requestUri));
151 public Task<HttpResponseMessage> GetAsync (string requestUri, HttpCompletionOption completionOption)
153 return SendAsync (new HttpRequestMessage (HttpMethod.Get, requestUri), completionOption);
156 public Task<HttpResponseMessage> GetAsync (string requestUri, HttpCompletionOption completionOption, CancellationToken cancellationToken)
158 return SendAsync (new HttpRequestMessage (HttpMethod.Get, requestUri), completionOption, cancellationToken);
161 public Task<HttpResponseMessage> GetAsync (Uri requestUri)
163 return SendAsync (new HttpRequestMessage (HttpMethod.Get, requestUri));
166 public Task<HttpResponseMessage> GetAsync (Uri requestUri, CancellationToken cancellationToken)
168 return SendAsync (new HttpRequestMessage (HttpMethod.Get, requestUri), cancellationToken);
171 public Task<HttpResponseMessage> GetAsync (Uri requestUri, HttpCompletionOption completionOption)
173 return SendAsync (new HttpRequestMessage (HttpMethod.Get, requestUri), completionOption);
176 public Task<HttpResponseMessage> GetAsync (Uri requestUri, HttpCompletionOption completionOption, CancellationToken cancellationToken)
178 return SendAsync (new HttpRequestMessage (HttpMethod.Get, requestUri), completionOption, cancellationToken);
181 public Task<HttpResponseMessage> PostAsync (string requestUri, HttpContent content)
183 return SendAsync (new HttpRequestMessage (HttpMethod.Post, requestUri) { Content = content });
186 public Task<HttpResponseMessage> PostAsync (string requestUri, HttpContent content, CancellationToken cancellationToken)
188 return SendAsync (new HttpRequestMessage (HttpMethod.Post, requestUri) { Content = content }, cancellationToken);
191 public Task<HttpResponseMessage> PostAsync (Uri requestUri, HttpContent content)
193 return SendAsync (new HttpRequestMessage (HttpMethod.Post, requestUri) { Content = content });
196 public Task<HttpResponseMessage> PostAsync (Uri requestUri, HttpContent content, CancellationToken cancellationToken)
198 return SendAsync (new HttpRequestMessage (HttpMethod.Post, requestUri) { Content = content }, cancellationToken);
201 public Task<HttpResponseMessage> PutAsync (Uri requestUri, HttpContent content)
203 return SendAsync (new HttpRequestMessage (HttpMethod.Put, requestUri) { Content = content });
206 public Task<HttpResponseMessage> PutAsync (Uri requestUri, HttpContent content, CancellationToken cancellationToken)
208 return SendAsync (new HttpRequestMessage (HttpMethod.Put, requestUri) { Content = content }, cancellationToken);
211 public Task<HttpResponseMessage> PutAsync (string requestUri, HttpContent content)
213 return SendAsync (new HttpRequestMessage (HttpMethod.Put, requestUri) { Content = content });
216 public Task<HttpResponseMessage> PutAsync (string requestUri, HttpContent content, CancellationToken cancellationToken)
218 return SendAsync (new HttpRequestMessage (HttpMethod.Put, requestUri) { Content = content }, cancellationToken);
221 public Task<HttpResponseMessage> SendAsync (HttpRequestMessage request)
223 return SendAsync (request, HttpCompletionOption.ResponseContentRead, CancellationToken.None);
226 public Task<HttpResponseMessage> SendAsync (HttpRequestMessage request, HttpCompletionOption completionOption)
228 return SendAsync (request, completionOption, CancellationToken.None);
231 public Task<HttpResponseMessage> SendAsync (HttpRequestMessage request, CancellationToken cancellationToken)
233 return SendAsync (request, HttpCompletionOption.ResponseContentRead, cancellationToken);
236 public Task<HttpResponseMessage> SendAsync (HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken)
239 throw new ArgumentNullException ("request");
241 if (request.SetIsUsed ())
242 throw new InvalidOperationException ("Cannot send the same request message multiple times");
244 if (request.RequestUri == null) {
245 if (base_address == null)
246 throw new InvalidOperationException ("The request URI must either be an absolute URI or BaseAddress must be set");
248 request.RequestUri = base_address;
251 if (headers != null) {
252 request.Headers.AddHeaders (headers);
256 if (cancellation_token == null)
257 cancellation_token = new CancellationTokenSource ();
259 using (var cts = CancellationTokenSource.CreateLinkedTokenSource (cancellation_token.Token, cancellationToken)) {
260 cts.CancelAfter (timeout);
262 var response = handler.SendAsync (request, cts.Token);
263 //if (response == null)
264 // throw new InvalidOperationException ("Handler failed to return a response");
269 cancellation_token.Dispose ();
270 cancellation_token = null;