Add System.Net.Http to build
[mono.git] / mcs / class / System.Net.Http / System.Net.Http / HttpClient.cs
1 //
2 // HttpClient.cs
3 //
4 // Authors:
5 //      Marek Safar  <marek.safar@gmail.com>
6 //
7 // Copyright (C) 2011 Xamarin Inc (http://www.xamarin.com)
8 //
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:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
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.
27 //
28
29 using System.Threading;
30 using System.Net.Http.Headers;
31 using System.Threading.Tasks;
32
33 namespace System.Net.Http
34 {
35         public class HttpClient : IDisposable
36         {
37                 static readonly TimeSpan TimeoutDefault = TimeSpan.FromSeconds (100);
38
39                 Uri base_address;
40                 CancellationTokenSource cancellation_token;
41                 bool disposed;
42                 readonly HttpMessageHandler handler;
43                 HttpRequestHeaders headers;
44                 int buffer_size;
45                 TimeSpan timeout;
46
47                 public HttpClient ()
48                         : this (null)
49                 {
50                 }
51
52                 public HttpClient (HttpMessageHandler handler)
53                 {
54                         this.handler = handler ?? new HttpClientHandler ();
55                         buffer_size = 0x10000;
56                         timeout = TimeoutDefault;
57                 }
58
59                 public Uri BaseAddress {
60                         get {
61                                 return base_address;
62                         }
63                         set {
64                                 base_address = value;
65                         }
66                 }
67
68                 public HttpRequestHeaders DefaultRequestHeaders {
69                         get {
70                                 return headers ?? (headers = new HttpRequestHeaders ());
71                         }
72                 }
73
74                 public int MaxResponseContentBufferSize {
75                         get {
76                                 return buffer_size;
77                         }
78                         set {
79                                 if (value <= 0)
80                                         throw new ArgumentOutOfRangeException ();
81
82                                 buffer_size = value;
83                         }
84                 }
85
86                 public TimeSpan Timeout {
87                         get {
88                                 return timeout;
89                         }
90                         set {
91                                 if (value != System.Threading.Timeout.InfiniteTimeSpan && value < TimeSpan.Zero)
92                                         throw new ArgumentOutOfRangeException ();
93
94                                 timeout = value;
95                         }
96                 }
97
98                 public void CancelPendingRequests ()
99                 {
100                         if (cancellation_token != null)
101                                 cancellation_token.Cancel ();
102
103                         cancellation_token = new CancellationTokenSource ();
104                 }
105  
106                 public void Dispose ()
107                 {
108                         Dispose (true);
109                 }
110                 
111                 protected virtual void Dispose (bool disposing)
112                 {
113                         if (disposing && !disposed) {
114                                 disposed = true;
115
116                                 if (cancellation_token != null)
117                                         cancellation_token.Dispose ();
118                         }
119                 }
120
121                 public Task<HttpResponseMessage> DeleteAsync (string requestUri)
122                 {
123                         return SendAsync (new HttpRequestMessage (HttpMethod.Delete, requestUri));
124                 }
125
126                 public Task<HttpResponseMessage> DeleteAsync (string requestUri, CancellationToken cancellationToken)
127                 {
128                         return SendAsync (new HttpRequestMessage (HttpMethod.Delete, requestUri), cancellationToken);
129                 }
130
131                 public Task<HttpResponseMessage> DeleteAsync (Uri requestUri)
132                 {
133                         return SendAsync (new HttpRequestMessage (HttpMethod.Delete, requestUri));
134                 }
135
136                 public Task<HttpResponseMessage> DeleteAsync (Uri requestUri, CancellationToken cancellationToken)
137                 {
138                         return SendAsync (new HttpRequestMessage (HttpMethod.Delete, requestUri), cancellationToken);
139                 }
140
141                 public Task<HttpResponseMessage> GetAsync (string requestUri)
142                 {
143                         return SendAsync (new HttpRequestMessage (HttpMethod.Get, requestUri));
144                 }
145
146                 public Task<HttpResponseMessage> GetAsync (string requestUri, CancellationToken cancellationToken)
147                 {
148                         return SendAsync (new HttpRequestMessage (HttpMethod.Get, requestUri));
149                 }
150
151                 public Task<HttpResponseMessage> GetAsync (string requestUri, HttpCompletionOption completionOption)
152                 {
153                         return SendAsync (new HttpRequestMessage (HttpMethod.Get, requestUri), completionOption);
154                 }
155
156                 public Task<HttpResponseMessage> GetAsync (string requestUri, HttpCompletionOption completionOption, CancellationToken cancellationToken)
157                 {
158                         return SendAsync (new HttpRequestMessage (HttpMethod.Get, requestUri), completionOption, cancellationToken);
159                 }
160
161                 public Task<HttpResponseMessage> GetAsync (Uri requestUri)
162                 {
163                         return SendAsync (new HttpRequestMessage (HttpMethod.Get, requestUri));
164                 }
165
166                 public Task<HttpResponseMessage> GetAsync (Uri requestUri, CancellationToken cancellationToken)
167                 {
168                         return SendAsync (new HttpRequestMessage (HttpMethod.Get, requestUri), cancellationToken);
169                 }
170
171                 public Task<HttpResponseMessage> GetAsync (Uri requestUri, HttpCompletionOption completionOption)
172                 {
173                         return SendAsync (new HttpRequestMessage (HttpMethod.Get, requestUri), completionOption);
174                 }
175
176                 public Task<HttpResponseMessage> GetAsync (Uri requestUri, HttpCompletionOption completionOption, CancellationToken cancellationToken)
177                 {
178                         return SendAsync (new HttpRequestMessage (HttpMethod.Get, requestUri), completionOption, cancellationToken);
179                 }
180
181                 public Task<HttpResponseMessage> PostAsync (string requestUri, HttpContent content)
182                 {
183                         return SendAsync (new HttpRequestMessage (HttpMethod.Post, requestUri) { Content = content });
184                 }
185
186                 public Task<HttpResponseMessage> PostAsync (string requestUri, HttpContent content, CancellationToken cancellationToken)
187                 {
188                         return SendAsync (new HttpRequestMessage (HttpMethod.Post, requestUri) { Content = content }, cancellationToken);
189                 }
190
191                 public Task<HttpResponseMessage> PostAsync (Uri requestUri, HttpContent content)
192                 {
193                         return SendAsync (new HttpRequestMessage (HttpMethod.Post, requestUri) { Content = content });
194                 }
195
196                 public Task<HttpResponseMessage> PostAsync (Uri requestUri, HttpContent content, CancellationToken cancellationToken)
197                 {
198                         return SendAsync (new HttpRequestMessage (HttpMethod.Post, requestUri) { Content = content }, cancellationToken);
199                 }
200
201                 public Task<HttpResponseMessage> PutAsync (Uri requestUri, HttpContent content)
202                 {
203                         return SendAsync (new HttpRequestMessage (HttpMethod.Put, requestUri) { Content = content });
204                 }
205
206                 public Task<HttpResponseMessage> PutAsync (Uri requestUri, HttpContent content, CancellationToken cancellationToken)
207                 {
208                         return SendAsync (new HttpRequestMessage (HttpMethod.Put, requestUri) { Content = content }, cancellationToken);
209                 }
210
211                 public Task<HttpResponseMessage> PutAsync (string requestUri, HttpContent content)
212                 {
213                         return SendAsync (new HttpRequestMessage (HttpMethod.Put, requestUri) { Content = content });
214                 }
215
216                 public Task<HttpResponseMessage> PutAsync (string requestUri, HttpContent content, CancellationToken cancellationToken)
217                 {
218                         return SendAsync (new HttpRequestMessage (HttpMethod.Put, requestUri) { Content = content }, cancellationToken);
219                 }
220
221                 public Task<HttpResponseMessage> SendAsync (HttpRequestMessage request)
222                 {
223                         return SendAsync (request, HttpCompletionOption.ResponseContentRead, CancellationToken.None);
224                 }
225
226                 public Task<HttpResponseMessage> SendAsync (HttpRequestMessage request, HttpCompletionOption completionOption)
227                 {
228                         return SendAsync (request, completionOption, CancellationToken.None);
229                 }
230
231                 public Task<HttpResponseMessage> SendAsync (HttpRequestMessage request, CancellationToken cancellationToken)
232                 {
233                         return SendAsync (request, HttpCompletionOption.ResponseContentRead, cancellationToken);
234                 }
235
236                 public Task<HttpResponseMessage> SendAsync (HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken)
237                 {
238                         if (request == null)
239                                 throw new ArgumentNullException ("request");
240
241                         if (request.SetIsUsed ())
242                                 throw new InvalidOperationException ("Cannot send the same request message multiple times");
243
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");
247
248                                 request.RequestUri = base_address;
249                         }
250
251                         if (headers != null) {
252                                 request.Headers.AddHeaders (headers);
253                         }
254
255                         try {
256                                 if (cancellation_token == null)
257                                         cancellation_token = new CancellationTokenSource ();
258
259                                 using (var cts = CancellationTokenSource.CreateLinkedTokenSource (cancellation_token.Token, cancellationToken)) {
260                                         cts.CancelAfter (timeout);
261
262                                         var response = handler.SendAsync (request, cts.Token);
263                                         //if (response == null)
264                                         //      throw new InvalidOperationException ("Handler failed to return a response");
265
266                                         return response;
267                                 }
268                         } finally {
269                                 cancellation_token.Dispose ();
270                                 cancellation_token = null;
271                         }
272                 }
273         }
274 }