From 61f50dbbf518aa13d02beb03490a32181780a38e Mon Sep 17 00:00:00 2001 From: moberacker Date: Thu, 21 Feb 2019 11:13:19 +0100 Subject: [PATCH] initial checkin --- Log4ALA/HttpRequestExtensions.cs | 24 ++++++++++++++++++ Log4ALA/TimeoutHandler.cs | 43 ++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 Log4ALA/HttpRequestExtensions.cs create mode 100644 Log4ALA/TimeoutHandler.cs diff --git a/Log4ALA/HttpRequestExtensions.cs b/Log4ALA/HttpRequestExtensions.cs new file mode 100644 index 0000000..ce4492c --- /dev/null +++ b/Log4ALA/HttpRequestExtensions.cs @@ -0,0 +1,24 @@ +using System; +using System.Net.Http; + +namespace Log4ALA +{ + public static class HttpRequestExtensions + { + private static string TimeoutPropertyKey = "RequestTimeout"; + + public static void SetTimeout(this HttpRequestMessage request, TimeSpan? timeout) + { + if (request == null) throw new ArgumentNullException(nameof(request)); + request.Properties[TimeoutPropertyKey] = timeout; + } + + public static TimeSpan? GetTimeout(this HttpRequestMessage request) + { + if (request == null) throw new ArgumentNullException(nameof(request)); + if (request.Properties.TryGetValue(TimeoutPropertyKey, out var value) && value is TimeSpan timeout) + return timeout; + return null; + } + } +} diff --git a/Log4ALA/TimeoutHandler.cs b/Log4ALA/TimeoutHandler.cs new file mode 100644 index 0000000..5abf621 --- /dev/null +++ b/Log4ALA/TimeoutHandler.cs @@ -0,0 +1,43 @@ +using System; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; + +namespace Log4ALA +{ + public class TimeoutHandler : DelegatingHandler + { + public TimeSpan DefaultTimeout { get; set; } = TimeSpan.FromSeconds(100); + + protected async override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + using (var cts = GetCancellationTokenSource(request, cancellationToken)) + { + try + { + return await base.SendAsync(request, cts?.Token ?? cancellationToken); + } + catch (OperationCanceledException) when (!cancellationToken.IsCancellationRequested) + { + throw new TimeoutException(); + } + } + } + + private CancellationTokenSource GetCancellationTokenSource(HttpRequestMessage request, CancellationToken cancellationToken) + { + var timeout = request.GetTimeout() ?? DefaultTimeout; + if (timeout == Timeout.InfiniteTimeSpan) + { + // No need to create a CTS if there's no timeout + return null; + } + else + { + var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); + cts.CancelAfter(timeout); + return cts; + } + } + } +}