From 014ad04b1c16f8e9ac9f1ee479b92145672e3390 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Luthi?= Date: Sun, 4 Sep 2022 15:57:07 +0200 Subject: [PATCH] Add an authorization header value getter property that supports cancellation In addition to `AuthorizationHeaderValueGetter` and `AuthorizationHeaderValueWithParamGetter`, a new `AuthorizationHeaderValueWithCancellationTokenGetter` is added with support for CancellationToken. Also, the `AuthenticatedHttpClientHandler` and `AuthenticatedParameterizedHttpClientHandler` internal classes have been merged into a single `AuthenticatedHttpClientHandler` class to reduce code duplication. --- .../HttpClientFactoryExtensions.cs | 8 +++-- .../AuthenticatedClientHandlerTests.cs | 18 ++--------- Refit/AuthenticatedHttpClientHandler.cs | 6 ++-- ...enticatedParameterizedHttpClientHandler.cs | 32 ------------------- Refit/RefitSettings.cs | 5 +++ Refit/RestService.cs | 12 ++++--- 6 files changed, 24 insertions(+), 57 deletions(-) delete mode 100644 Refit/AuthenticatedParameterizedHttpClientHandler.cs diff --git a/Refit.HttpClientFactory/HttpClientFactoryExtensions.cs b/Refit.HttpClientFactory/HttpClientFactoryExtensions.cs index 5d185638b..4aa30fa8b 100644 --- a/Refit.HttpClientFactory/HttpClientFactoryExtensions.cs +++ b/Refit.HttpClientFactory/HttpClientFactoryExtensions.cs @@ -102,11 +102,15 @@ public static IHttpClientBuilder AddRefitClient(this IServiceCollection services if (settings.AuthorizationHeaderValueGetter != null) { - innerHandler = new AuthenticatedHttpClientHandler(settings.AuthorizationHeaderValueGetter, innerHandler); + innerHandler = new AuthenticatedHttpClientHandler((_, _) => settings.AuthorizationHeaderValueGetter(), innerHandler); } else if (settings.AuthorizationHeaderValueWithParamGetter != null) { - innerHandler = new AuthenticatedParameterizedHttpClientHandler(settings.AuthorizationHeaderValueWithParamGetter, innerHandler); + innerHandler = new AuthenticatedHttpClientHandler((request, _) => settings.AuthorizationHeaderValueWithParamGetter(request), innerHandler); + } + else if (settings.AuthorizationHeaderValueWithCancellationTokenGetter != null) + { + innerHandler = new AuthenticatedHttpClientHandler(settings.AuthorizationHeaderValueWithCancellationTokenGetter, innerHandler); } } diff --git a/Refit.Tests/AuthenticatedClientHandlerTests.cs b/Refit.Tests/AuthenticatedClientHandlerTests.cs index 9a4df23d2..aee850f0b 100644 --- a/Refit.Tests/AuthenticatedClientHandlerTests.cs +++ b/Refit.Tests/AuthenticatedClientHandlerTests.cs @@ -42,15 +42,7 @@ public interface IAuthenticatedServiceWithHeaders [Fact] public void DefaultHandlerIsHttpClientHandler() { - var handler = new AuthenticatedHttpClientHandler((() => Task.FromResult(string.Empty))); - - Assert.IsType(handler.InnerHandler); - } - - [Fact] - public void DefaultHandlerIsHttpClientHandlerWithParam() - { - var handler = new AuthenticatedParameterizedHttpClientHandler(((request) => Task.FromResult(string.Empty))); + var handler = new AuthenticatedHttpClientHandler(((_, _) => Task.FromResult(string.Empty))); Assert.IsType(handler.InnerHandler); } @@ -61,12 +53,6 @@ public void NullTokenGetterThrows() Assert.Throws(() => new AuthenticatedHttpClientHandler(null)); } - [Fact] - public void NullTokenGetterThrowsWithParam() - { - Assert.Throws(() => new AuthenticatedParameterizedHttpClientHandler(null)); - } - [Fact] public async void AuthenticatedHandlerIgnoresUnAuth() { @@ -142,7 +128,7 @@ public async void AuthenticatedHandlerWithTokenInParameterUsesAuth() { var handler = new MockHttpMessageHandler(); var settings = new RefitSettings() - { + { HttpMessageHandlerFactory = () => handler }; diff --git a/Refit/AuthenticatedHttpClientHandler.cs b/Refit/AuthenticatedHttpClientHandler.cs index 42cc82d41..8f10172f2 100644 --- a/Refit/AuthenticatedHttpClientHandler.cs +++ b/Refit/AuthenticatedHttpClientHandler.cs @@ -8,9 +8,9 @@ namespace Refit { class AuthenticatedHttpClientHandler : DelegatingHandler { - readonly Func> getToken; + readonly Func> getToken; - public AuthenticatedHttpClientHandler(Func> getToken, HttpMessageHandler? innerHandler = null) + public AuthenticatedHttpClientHandler(Func> getToken, HttpMessageHandler? innerHandler = null) : base(innerHandler ?? new HttpClientHandler()) { this.getToken = getToken ?? throw new ArgumentNullException(nameof(getToken)); @@ -22,7 +22,7 @@ protected override async Task SendAsync(HttpRequestMessage var auth = request.Headers.Authorization; if (auth != null) { - var token = await getToken().ConfigureAwait(false); + var token = await getToken(request, cancellationToken).ConfigureAwait(false); request.Headers.Authorization = new AuthenticationHeaderValue(auth.Scheme, token); } diff --git a/Refit/AuthenticatedParameterizedHttpClientHandler.cs b/Refit/AuthenticatedParameterizedHttpClientHandler.cs deleted file mode 100644 index a0e05f563..000000000 --- a/Refit/AuthenticatedParameterizedHttpClientHandler.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Threading; -using System.Threading.Tasks; - -namespace Refit -{ - class AuthenticatedParameterizedHttpClientHandler : DelegatingHandler - { - readonly Func> getToken; - - public AuthenticatedParameterizedHttpClientHandler(Func> getToken, HttpMessageHandler? innerHandler = null) - : base(innerHandler ?? new HttpClientHandler()) - { - this.getToken = getToken ?? throw new ArgumentNullException(nameof(getToken)); - } - - protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) - { - // See if the request has an authorize header - var auth = request.Headers.Authorization; - if (auth != null) - { - var token = await getToken(request).ConfigureAwait(false); - request.Headers.Authorization = new AuthenticationHeaderValue(auth.Scheme, token); - } - - return await base.SendAsync(request, cancellationToken).ConfigureAwait(false); - } - } -} diff --git a/Refit/RefitSettings.cs b/Refit/RefitSettings.cs index 3d6835838..686bd77f8 100644 --- a/Refit/RefitSettings.cs +++ b/Refit/RefitSettings.cs @@ -53,6 +53,11 @@ public RefitSettings( /// public Func>? AuthorizationHeaderValueWithParamGetter { get; set; } + /// + /// Supply a function to provide the Authorization header. Does not work if you supply an HttpClient instance. + /// + public Func>? AuthorizationHeaderValueWithCancellationTokenGetter { get; set; } + /// /// Supply a custom inner HttpMessageHandler. Does not work if you supply an HttpClient instance. /// diff --git a/Refit/RestService.cs b/Refit/RestService.cs index 4da9cd63c..5930cac6d 100644 --- a/Refit/RestService.cs +++ b/Refit/RestService.cs @@ -110,7 +110,7 @@ public static object For(Type refitInterfaceType, HttpClient client, RefitSettin public static object For(Type refitInterfaceType, string hostUrl, RefitSettings? settings) { var client = CreateHttpClient(hostUrl, settings); - + return For(refitInterfaceType, client, settings); } @@ -120,7 +120,7 @@ public static object For(Type refitInterfaceType, string hostUrl, RefitSettings? /// Interface to create the implementation for. /// Base address the implementation will use. /// An instance that implements . - public static object For(Type refitInterfaceType, string hostUrl) => For(refitInterfaceType, hostUrl, null); + public static object For(Type refitInterfaceType, string hostUrl) => For(refitInterfaceType, hostUrl, null); /// /// Create an with as the base address. @@ -149,11 +149,15 @@ public static HttpClient CreateHttpClient(string hostUrl, RefitSettings? setting if (settings.AuthorizationHeaderValueGetter != null) { - innerHandler = new AuthenticatedHttpClientHandler(settings.AuthorizationHeaderValueGetter, innerHandler); + innerHandler = new AuthenticatedHttpClientHandler((_, _) => settings.AuthorizationHeaderValueGetter(), innerHandler); } else if (settings.AuthorizationHeaderValueWithParamGetter != null) { - innerHandler = new AuthenticatedParameterizedHttpClientHandler(settings.AuthorizationHeaderValueWithParamGetter, innerHandler); + innerHandler = new AuthenticatedHttpClientHandler((request, _) => settings.AuthorizationHeaderValueWithParamGetter(request), innerHandler); + } + else if (settings.AuthorizationHeaderValueWithCancellationTokenGetter != null) + { + innerHandler = new AuthenticatedHttpClientHandler(settings.AuthorizationHeaderValueWithCancellationTokenGetter, innerHandler); } }