X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2FSystem.Net.Http%2FSystem.Net.Http%2FHttpClient.cs;h=c9fd2354abe136be56708c73b9a2bf30ff6f2098;hb=3741d16503a973a99c724bdab9a255a5f07a3637;hp=2714835fee85f637165a8799484d14482ff6c1fa;hpb=c133ae2dc82c0533f5790333a3c93b2635b9c43c;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 2714835fee8..c9fd2354abe 100644 --- a/mcs/class/System.Net.Http/System.Net.Http/HttpClient.cs +++ b/mcs/class/System.Net.Http/System.Net.Http/HttpClient.cs @@ -33,21 +33,23 @@ using System.IO; namespace System.Net.Http { - public class HttpClient : HttpMessageInvoker + public partial class HttpClient : HttpMessageInvoker { static readonly TimeSpan TimeoutDefault = TimeSpan.FromSeconds (100); Uri base_address; - CancellationTokenSource cancellation_token; + CancellationTokenSource cts; bool disposed; HttpRequestHeaders headers; long buffer_size; TimeSpan timeout; +#if !XAMARIN_MODERN public HttpClient () : this (new HttpClientHandler (), true) { } +#endif public HttpClient (HttpMessageHandler handler) : this (handler, true) @@ -59,6 +61,7 @@ namespace System.Net.Http { buffer_size = int.MaxValue; timeout = TimeoutDefault; + cts = new CancellationTokenSource (); } public Uri BaseAddress { @@ -93,7 +96,7 @@ namespace System.Net.Http return timeout; } set { - if (value != System.Threading.Timeout.InfiniteTimeSpan && value < TimeSpan.Zero) + if (value != System.Threading.Timeout.InfiniteTimeSpan && (value <= TimeSpan.Zero || value.Ticks > int.MaxValue)) throw new ArgumentOutOfRangeException (); timeout = value; @@ -102,10 +105,9 @@ namespace System.Net.Http public void CancelPendingRequests () { - if (cancellation_token != null) - cancellation_token.Cancel (); - - cancellation_token = new CancellationTokenSource (); + // 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 override void Dispose (bool disposing) @@ -113,8 +115,7 @@ namespace System.Net.Http if (disposing && !disposed) { disposed = true; - if (cancellation_token != null) - cancellation_token.Dispose (); + cts.Dispose (); } base.Dispose (disposing); @@ -147,7 +148,7 @@ namespace System.Net.Http public Task GetAsync (string requestUri, CancellationToken cancellationToken) { - return SendAsync (new HttpRequestMessage (HttpMethod.Get, requestUri)); + return SendAsync (new HttpRequestMessage (HttpMethod.Get, requestUri), cancellationToken); } public Task GetAsync (string requestUri, HttpCompletionOption completionOption) @@ -243,16 +244,17 @@ namespace System.Net.Http if (request.SetIsUsed ()) throw new InvalidOperationException ("Cannot send the same request message multiple times"); - if (request.RequestUri == null) { + var uri = request.RequestUri; + if (uri == null) { if (base_address == null) 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) { + } else if (!uri.IsAbsoluteUri || uri.Scheme == Uri.UriSchemeFile && uri.OriginalString.StartsWith ("/", StringComparison.Ordinal)) { 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); + request.RequestUri = new Uri (base_address, uri); } if (headers != null) { @@ -264,33 +266,25 @@ namespace System.Net.Http async Task SendAsyncWorker (HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken) { - try { - if (cancellation_token == null) - cancellation_token = new CancellationTokenSource (); + using (var lcts = CancellationTokenSource.CreateLinkedTokenSource (cts.Token, cancellationToken)) { + lcts.CancelAfter (timeout); - using (var cts = CancellationTokenSource.CreateLinkedTokenSource (cancellation_token.Token, cancellationToken)) { - cts.CancelAfter (timeout); - - var task = base.SendAsync (request, cts.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); - } + var task = base.SendAsync (request, lcts.Token); + if (task == null) + throw new InvalidOperationException ("Handler failed to return a value"); - return response; + 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); } - } finally { - cancellation_token.Dispose (); - cancellation_token = null; + + return response; } } @@ -312,14 +306,14 @@ namespace System.Net.Http public async Task GetStreamAsync (string requestUri) { - var resp = await GetAsync (requestUri, HttpCompletionOption.ResponseContentRead).ConfigureAwait (false); + var resp = await GetAsync (requestUri, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait (false); resp.EnsureSuccessStatusCode (); return await resp.Content.ReadAsStreamAsync ().ConfigureAwait (false); } public async Task GetStreamAsync (Uri requestUri) { - var resp = await GetAsync (requestUri, HttpCompletionOption.ResponseContentRead).ConfigureAwait (false); + var resp = await GetAsync (requestUri, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait (false); resp.EnsureSuccessStatusCode (); return await resp.Content.ReadAsStreamAsync ().ConfigureAwait (false); }