X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2FSystem.Net.Http%2FSystem.Net.Http%2FHttpClient.cs;h=1e1fcbf1021ffd69ea9e7814a9b69bbffec4c2c5;hb=392bae3c453763e8f887f447678ab0202a36228a;hp=92e22982b87b8fe66ff164e4117fb4738ca23bd1;hpb=23410780cf35004c93f96261666798f895588f19;p=mono.git diff --git a/mcs/class/System.Net.Http/System.Net.Http/HttpClient.cs b/mcs/class/System.Net.Http/System.Net.Http/HttpClient.cs index 92e22982b87..1e1fcbf1021 100644 --- a/mcs/class/System.Net.Http/System.Net.Http/HttpClient.cs +++ b/mcs/class/System.Net.Http/System.Net.Http/HttpClient.cs @@ -29,31 +29,37 @@ using System.Threading; using System.Net.Http.Headers; using System.Threading.Tasks; +using System.IO; namespace System.Net.Http { - public class HttpClient : IDisposable + public class HttpClient : HttpMessageInvoker { static readonly TimeSpan TimeoutDefault = TimeSpan.FromSeconds (100); Uri base_address; - CancellationTokenSource cancellation_token; + CancellationTokenSource cts; bool disposed; - readonly HttpMessageHandler handler; HttpRequestHeaders headers; - int buffer_size; + long buffer_size; TimeSpan timeout; public HttpClient () - : this (null) + : this (new HttpClientHandler (), true) { } - + public HttpClient (HttpMessageHandler handler) + : this (handler, true) + { + } + + public HttpClient (HttpMessageHandler handler, bool disposeHandler) + : base (handler, disposeHandler) { - this.handler = handler ?? new HttpClientHandler (); - buffer_size = 0x10000; + buffer_size = int.MaxValue; timeout = TimeoutDefault; + cts = new CancellationTokenSource (); } public Uri BaseAddress { @@ -71,7 +77,7 @@ namespace System.Net.Http } } - public int MaxResponseContentBufferSize { + public long MaxResponseContentBufferSize { get { return buffer_size; } @@ -97,25 +103,20 @@ namespace System.Net.Http public void CancelPendingRequests () { - if (cancellation_token != null) - cancellation_token.Cancel (); - - cancellation_token = new CancellationTokenSource (); - } - - public void Dispose () - { - Dispose (true); + // Cancel only any already running requests not any new request after this cancellation + using (var c = Interlocked.Exchange (ref cts, new CancellationTokenSource ())) + c.Cancel (); } - - protected virtual void Dispose (bool disposing) + + protected override void Dispose (bool disposing) { if (disposing && !disposed) { disposed = true; - if (cancellation_token != null) - cancellation_token.Dispose (); + cts.Dispose (); } + + base.Dispose (disposing); } public Task DeleteAsync (string requestUri) @@ -228,7 +229,7 @@ namespace System.Net.Http return SendAsync (request, completionOption, CancellationToken.None); } - public Task SendAsync (HttpRequestMessage request, CancellationToken cancellationToken) + public override Task SendAsync (HttpRequestMessage request, CancellationToken cancellationToken) { return SendAsync (request, HttpCompletionOption.ResponseContentRead, cancellationToken); } @@ -246,33 +247,87 @@ namespace System.Net.Http throw new InvalidOperationException ("The request URI must either be an absolute URI or BaseAddress must be set"); request.RequestUri = base_address; + } else if (!request.RequestUri.IsAbsoluteUri) { + if (base_address == null) + throw new InvalidOperationException ("The request URI must either be an absolute URI or BaseAddress must be set"); + + request.RequestUri = new Uri (base_address, request.RequestUri); } if (headers != null) { request.Headers.AddHeaders (headers); } - return SendAsyncWorker (request, cancellationToken); + return SendAsyncWorker (request, completionOption, cancellationToken); + } + + async Task SendAsyncWorker (HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken) + { + using (var lcts = CancellationTokenSource.CreateLinkedTokenSource (cts.Token, cancellationToken)) { + lcts.CancelAfter (timeout); + + var task = base.SendAsync (request, lcts.Token); + if (task == null) + throw new InvalidOperationException ("Handler failed to return a value"); + + var response = await task.ConfigureAwait (false); + if (response == null) + throw new InvalidOperationException ("Handler failed to return a response"); + + // + // Read the content when default HttpCompletionOption.ResponseContentRead is set + // + if (response.Content != null && (completionOption & HttpCompletionOption.ResponseHeadersRead) == 0) { + await response.Content.LoadIntoBufferAsync (MaxResponseContentBufferSize).ConfigureAwait (false); + } + + return response; + } + } + + public async Task GetByteArrayAsync (string requestUri) + { + using (var resp = await GetAsync (requestUri, HttpCompletionOption.ResponseContentRead).ConfigureAwait (false)) { + resp.EnsureSuccessStatusCode (); + return await resp.Content.ReadAsByteArrayAsync ().ConfigureAwait (false); + } } - async Task SendAsyncWorker (HttpRequestMessage request, CancellationToken cancellationToken) + public async Task GetByteArrayAsync (Uri requestUri) { - try { - if (cancellation_token == null) - cancellation_token = new CancellationTokenSource (); + using (var resp = await GetAsync (requestUri, HttpCompletionOption.ResponseContentRead).ConfigureAwait (false)) { + resp.EnsureSuccessStatusCode (); + return await resp.Content.ReadAsByteArrayAsync ().ConfigureAwait (false); + } + } - using (var cts = CancellationTokenSource.CreateLinkedTokenSource (cancellation_token.Token, cancellationToken)) { - cts.CancelAfter (timeout); + public async Task GetStreamAsync (string requestUri) + { + var resp = await GetAsync (requestUri, HttpCompletionOption.ResponseContentRead).ConfigureAwait (false); + resp.EnsureSuccessStatusCode (); + return await resp.Content.ReadAsStreamAsync ().ConfigureAwait (false); + } - var response = await handler.SendAsync (request, cts.Token).ConfigureAwait (false); - if (response == null) - throw new InvalidOperationException ("Handler failed to return a response"); + public async Task GetStreamAsync (Uri requestUri) + { + var resp = await GetAsync (requestUri, HttpCompletionOption.ResponseContentRead).ConfigureAwait (false); + resp.EnsureSuccessStatusCode (); + return await resp.Content.ReadAsStreamAsync ().ConfigureAwait (false); + } - return response; - } - } finally { - cancellation_token.Dispose (); - cancellation_token = null; + public async Task GetStringAsync (string requestUri) + { + using (var resp = await GetAsync (requestUri, HttpCompletionOption.ResponseContentRead).ConfigureAwait (false)) { + resp.EnsureSuccessStatusCode (); + return await resp.Content.ReadAsStringAsync ().ConfigureAwait (false); + } + } + + public async Task GetStringAsync (Uri requestUri) + { + using (var resp = await GetAsync (requestUri, HttpCompletionOption.ResponseContentRead).ConfigureAwait (false)) { + resp.EnsureSuccessStatusCode (); + return await resp.Content.ReadAsStringAsync ().ConfigureAwait (false); } } }