From 00f76a3e6fc20073d88f12af027279eb45f9b456 Mon Sep 17 00:00:00 2001 From: Bastian Eicher Date: Mon, 11 May 2020 18:01:47 +0200 Subject: [PATCH] Replaced EndpointBase.HandleResponseAsync() with .HandleAsync() --- src/TypedRest.OAuth/OAuthHandler.cs | 13 ++++++++++--- .../Endpoints/Reactive/PollingEndpoint.cs | 4 ++-- src/TypedRest/Endpoints/EndpointBase.cs | 12 ++++++------ src/TypedRest/Endpoints/EntryEndpoint.cs | 2 +- .../Endpoints/Generic/CollectionEndpoint.cs | 6 +++--- src/TypedRest/Endpoints/Generic/ElementEndpoint.cs | 4 ++-- src/TypedRest/Endpoints/Generic/EtagEndpointBase.cs | 6 +++--- src/TypedRest/Endpoints/Generic/IndexerEndpoint.cs | 2 +- src/TypedRest/Endpoints/Raw/BlobEndpoint.cs | 8 ++++---- src/TypedRest/Endpoints/Raw/UploadEndpoint.cs | 2 +- src/TypedRest/Endpoints/Rpc/ActionEndpoint.cs | 2 +- src/TypedRest/Endpoints/Rpc/ConsumerEndpoint.cs | 2 +- src/TypedRest/Endpoints/Rpc/FunctionEndpoint.cs | 2 +- src/TypedRest/Endpoints/Rpc/ProducerEndpoint.cs | 2 +- src/TypedRest/Endpoints/Rpc/RpcEndpointBase.cs | 2 +- src/UnitTests/Endpoints/CustomEndpointTest.cs | 2 +- 16 files changed, 39 insertions(+), 32 deletions(-) diff --git a/src/TypedRest.OAuth/OAuthHandler.cs b/src/TypedRest.OAuth/OAuthHandler.cs index 21fa53ca..fb51369e 100644 --- a/src/TypedRest.OAuth/OAuthHandler.cs +++ b/src/TypedRest.OAuth/OAuthHandler.cs @@ -64,7 +64,7 @@ private async Task RequestAccessTokenAsync(CancellationToken cancellationToken) if (_oAuthOptions.Audience != null) request.Parameters[OidcConstants.TokenRequest.Audience] = _oAuthOptions.Audience; - var response = await _httpClient.Value.RequestClientCredentialsTokenAsync(request, cancellationToken).ConfigureAwait(false); + var response = await HandleAsync(() => _httpClient.Value.RequestClientCredentialsTokenAsync(request, cancellationToken)).ConfigureAwait(false); if (response.Exception != null) throw response.Exception; if (response.IsError) throw new AuthenticationException(response.Error); @@ -75,11 +75,18 @@ private async Task RequestAccessTokenAsync(CancellationToken cancellationToken) private async Task DiscoverTokenEndpointAsync(CancellationToken cancellationToken) { - var response = await _httpClient.Value.GetDiscoveryDocumentAsync(_oAuthOptions.Uri.OriginalString, cancellationToken); + var response = await HandleAsync(() => _httpClient.Value.GetDiscoveryDocumentAsync(_oAuthOptions.Uri.OriginalString, cancellationToken)).ConfigureAwait(false); + return response.TokenEndpoint; + } + + private static async Task HandleAsync(Func> request) + where TResponse : ProtocolResponse + { + var response = await request().ConfigureAwait(false); if (response.Exception != null) throw response.Exception; if (response.IsError) throw new AuthenticationException(response.Error); - return response.TokenEndpoint; + return response; } private async Task SendAuthenticatedAsync(HttpRequestMessage request, CancellationToken cancellationToken) diff --git a/src/TypedRest.Reactive/Endpoints/Reactive/PollingEndpoint.cs b/src/TypedRest.Reactive/Endpoints/Reactive/PollingEndpoint.cs index 62dc2ef8..f16fee0f 100644 --- a/src/TypedRest.Reactive/Endpoints/Reactive/PollingEndpoint.cs +++ b/src/TypedRest.Reactive/Endpoints/Reactive/PollingEndpoint.cs @@ -39,9 +39,9 @@ public PollingEndpoint(IEndpoint referrer, string relativeUri, Predicate HandleResponseAsync(Task responseTask) + protected override async Task HandleAsync(Func> request) { - var response = await base.HandleResponseAsync(responseTask); + var response = await base.HandleAsync(request); PollingInterval = response.Headers.RetryAfter?.Delta ?? (response.Headers.RetryAfter?.Date - DateTime.UtcNow) ?? diff --git a/src/TypedRest/Endpoints/EndpointBase.cs b/src/TypedRest/Endpoints/EndpointBase.cs index 05585979..793d2e02 100644 --- a/src/TypedRest/Endpoints/EndpointBase.cs +++ b/src/TypedRest/Endpoints/EndpointBase.cs @@ -90,11 +90,11 @@ public void SetDefaultLinkTemplate(string rel, string? href) /// /// Handles various cross-cutting concerns regarding a response message such as discovering links and handling errors. /// - /// A response promise for a request that has started executing. - /// The resolved . - protected virtual async Task HandleResponseAsync(Task responseTask) + /// A callback that performs the actual HTTP request. + /// The resolved . + protected virtual async Task HandleAsync(Func> request) { - var response = await responseTask.NoContext(); + var response = await request().NoContext(); (_links, _linkTemplates) = await LinkHandler.HandleAsync(response).NoContext(); @@ -135,7 +135,7 @@ public Uri Link(string rel) { try { - await HandleResponseAsync(HttpClient.HeadAsync(Uri)).NoContext(); + await HandleAsync(() => HttpClient.HeadAsync(Uri)).NoContext(); } catch (Exception ex) { @@ -170,7 +170,7 @@ public UriTemplate LinkTemplate(string rel) { try { - await HandleResponseAsync(HttpClient.HeadAsync(Uri)).NoContext(); + await HandleAsync(() => HttpClient.HeadAsync(Uri)).NoContext(); } catch (Exception ex) { diff --git a/src/TypedRest/Endpoints/EntryEndpoint.cs b/src/TypedRest/Endpoints/EntryEndpoint.cs index b5fa1252..438e0636 100644 --- a/src/TypedRest/Endpoints/EntryEndpoint.cs +++ b/src/TypedRest/Endpoints/EntryEndpoint.cs @@ -70,6 +70,6 @@ public EntryEndpoint(Uri uri, ICredentials? credentials = null, MediaTypeFormatt /// or /// Other non-success status code. public Task ReadMetaAsync(CancellationToken cancellationToken = default) - => HandleResponseAsync(HttpClient.GetAsync(Uri, cancellationToken)); + => HandleAsync(() => HttpClient.GetAsync(Uri, cancellationToken)); } } diff --git a/src/TypedRest/Endpoints/Generic/CollectionEndpoint.cs b/src/TypedRest/Endpoints/Generic/CollectionEndpoint.cs index ce0ea998..80d84db9 100644 --- a/src/TypedRest/Endpoints/Generic/CollectionEndpoint.cs +++ b/src/TypedRest/Endpoints/Generic/CollectionEndpoint.cs @@ -105,7 +105,7 @@ public virtual async Task> ReadRangeAsync(RangeItemHead Headers = {Range = new RangeHeaderValue {Ranges = {range}, Unit = RangeUnit}} }; - var response = await HandleResponseAsync(HttpClient.SendAsync(request, cancellationToken)).NoContext(); + var response = await HandleAsync(() => HttpClient.SendAsync(request, cancellationToken)).NoContext(); return new PartialResponse( elements: await response.Content.ReadAsAsync>(Serializer, cancellationToken).NoContext(), range: response.Content.Headers.ContentRange); @@ -117,7 +117,7 @@ public virtual async ITask CreateAsync(TEntity entity, Cancell { if (entity == null) throw new ArgumentNullException(nameof(entity)); - var response = await HandleResponseAsync(HttpClient.PostAsync(Uri, entity, Serializer, cancellationToken)).NoContext(); + var response = await HandleAsync(() => HttpClient.PostAsync(Uri, entity, Serializer, cancellationToken)).NoContext(); var elementEndpoint = _getElementEndpoint(this, response.Headers.Location ?? Uri); if (response.Content != null && elementEndpoint is ICachingEndpoint caching) @@ -131,7 +131,7 @@ public virtual Task CreateAllAsync(IEnumerable entities, CancellationTo { if (entities == null) throw new ArgumentNullException(nameof(entities)); - return HandleResponseAsync(HttpClient.PatchAsync(Uri, entities, Serializer, cancellationToken)); + return HandleAsync(() => HttpClient.PatchAsync(Uri, entities, Serializer, cancellationToken)); } public bool? SetAllAllowed => IsMethodAllowed(HttpMethod.Put); diff --git a/src/TypedRest/Endpoints/Generic/ElementEndpoint.cs b/src/TypedRest/Endpoints/Generic/ElementEndpoint.cs index d20663ef..3292d8a8 100644 --- a/src/TypedRest/Endpoints/Generic/ElementEndpoint.cs +++ b/src/TypedRest/Endpoints/Generic/ElementEndpoint.cs @@ -54,7 +54,7 @@ public async Task ExistsAsync(CancellationToken cancellationToken = defaul { try { - await HandleResponseAsync(HttpClient.HeadAsync(Uri, cancellationToken)).NoContext(); + await HandleAsync(() => HttpClient.HeadAsync(Uri, cancellationToken)).NoContext(); } catch (KeyNotFoundException) { @@ -82,7 +82,7 @@ public async Task ExistsAsync(CancellationToken cancellationToken = defaul { if (entity == null) throw new ArgumentNullException(nameof(entity)); - var response = await HandleResponseAsync(HttpClient.PatchAsync(Uri, entity, Serializer, cancellationToken)); + var response = await HandleAsync(() => HttpClient.PatchAsync(Uri, entity, Serializer, cancellationToken)); return response.Content == null ? default : await response.Content.ReadAsAsync(Serializer, cancellationToken); diff --git a/src/TypedRest/Endpoints/Generic/EtagEndpointBase.cs b/src/TypedRest/Endpoints/Generic/EtagEndpointBase.cs index 1056aa67..379cbdcc 100644 --- a/src/TypedRest/Endpoints/Generic/EtagEndpointBase.cs +++ b/src/TypedRest/Endpoints/Generic/EtagEndpointBase.cs @@ -57,7 +57,7 @@ protected async Task GetContentAsync(CancellationToken cancellation return cache.GetContent(); else { - await HandleResponseAsync(Task.FromResult(response)).NoContext(); + await HandleAsync(() => Task.FromResult(response)).NoContext(); if (response.Content == null) throw new KeyNotFoundException($"{Uri} returned no body."); ResponseCache = new ResponseCache(response); @@ -84,7 +84,7 @@ protected Task PutContentAsync(HttpContent content, Cancell if (cache?.ETag != null) request.Headers.IfMatch.Add(cache.ETag); ResponseCache = null; - return HandleResponseAsync(HttpClient.SendAsync(request, cancellationToken)); + return HandleAsync(() => HttpClient.SendAsync(request, cancellationToken)); } /// @@ -105,7 +105,7 @@ protected Task DeleteContentAsync(CancellationToken cancell if (cache?.ETag != null) request.Headers.IfMatch.Add(cache.ETag); ResponseCache = null; - return HandleResponseAsync(HttpClient.SendAsync(request, cancellationToken)); + return HandleAsync(() => HttpClient.SendAsync(request, cancellationToken)); } } } diff --git a/src/TypedRest/Endpoints/Generic/IndexerEndpoint.cs b/src/TypedRest/Endpoints/Generic/IndexerEndpoint.cs index f2e2e7b9..8caee0e7 100644 --- a/src/TypedRest/Endpoints/Generic/IndexerEndpoint.cs +++ b/src/TypedRest/Endpoints/Generic/IndexerEndpoint.cs @@ -45,7 +45,7 @@ private void SetupElementHandling() private static readonly Func _getElementEndpoint = GetConstructor(); public Task ProbeAsync(CancellationToken cancellationToken = default) - => HandleResponseAsync(HttpClient.OptionsAsync(Uri, cancellationToken)); + => HandleAsync(() => HttpClient.OptionsAsync(Uri, cancellationToken)); public virtual TElementEndpoint this[string id] { diff --git a/src/TypedRest/Endpoints/Raw/BlobEndpoint.cs b/src/TypedRest/Endpoints/Raw/BlobEndpoint.cs index de720dc8..3fcae73c 100644 --- a/src/TypedRest/Endpoints/Raw/BlobEndpoint.cs +++ b/src/TypedRest/Endpoints/Raw/BlobEndpoint.cs @@ -32,13 +32,13 @@ public BlobEndpoint(IEndpoint referrer, string relativeUri) {} public Task ProbeAsync(CancellationToken cancellationToken = default) - => HandleResponseAsync(HttpClient.OptionsAsync(Uri, cancellationToken)); + => HandleAsync(() => HttpClient.OptionsAsync(Uri, cancellationToken)); public bool? DownloadAllowed => IsMethodAllowed(HttpMethod.Get); public async Task DownloadAsync(CancellationToken cancellationToken = default) { - var response = await HandleResponseAsync(HttpClient.GetAsync(Uri, HttpCompletionOption.ResponseHeadersRead, cancellationToken)).NoContext(); + var response = await HandleAsync(() => HttpClient.GetAsync(Uri, HttpCompletionOption.ResponseHeadersRead, cancellationToken)).NoContext(); return await response.Content.ReadAsStreamAsync().NoContext(); } @@ -48,12 +48,12 @@ public Task UploadFromAsync(Stream stream, string? mimeType = null, Cancellation { var content = new StreamContent(stream); if (!string.IsNullOrEmpty(mimeType)) content.Headers.ContentType = MediaTypeHeaderValue.Parse(mimeType); - return HandleResponseAsync(HttpClient.PutAsync(Uri, content, cancellationToken)); + return HandleAsync(() => HttpClient.PutAsync(Uri, content, cancellationToken)); } public bool? DeleteAllowed => IsMethodAllowed(HttpMethod.Delete); public Task DeleteAsync(CancellationToken cancellationToken = default) - => HandleResponseAsync(HttpClient.DeleteAsync(Uri, cancellationToken)); + => HandleAsync(() => HttpClient.DeleteAsync(Uri, cancellationToken)); } } diff --git a/src/TypedRest/Endpoints/Raw/UploadEndpoint.cs b/src/TypedRest/Endpoints/Raw/UploadEndpoint.cs index 8425c034..fb4cb751 100644 --- a/src/TypedRest/Endpoints/Raw/UploadEndpoint.cs +++ b/src/TypedRest/Endpoints/Raw/UploadEndpoint.cs @@ -68,7 +68,7 @@ public Task UploadFromAsync(Stream stream, string? fileName = null, string? mime : new MultipartFormDataContent {{content, _formField, fileName}}; } - return HandleResponseAsync(HttpClient.PostAsync(Uri, content, cancellationToken)); + return HandleAsync(() => HttpClient.PostAsync(Uri, content, cancellationToken)); } } } diff --git a/src/TypedRest/Endpoints/Rpc/ActionEndpoint.cs b/src/TypedRest/Endpoints/Rpc/ActionEndpoint.cs index 02d3b270..aedc527f 100644 --- a/src/TypedRest/Endpoints/Rpc/ActionEndpoint.cs +++ b/src/TypedRest/Endpoints/Rpc/ActionEndpoint.cs @@ -29,6 +29,6 @@ public ActionEndpoint(IEndpoint referrer, string relativeUri) {} public Task InvokeAsync(CancellationToken cancellationToken = default) - => HandleResponseAsync(HttpClient.SendAsync(new HttpRequestMessage(HttpMethod.Post, Uri), cancellationToken)); + => HandleAsync(() => HttpClient.SendAsync(new HttpRequestMessage(HttpMethod.Post, Uri), cancellationToken)); } } diff --git a/src/TypedRest/Endpoints/Rpc/ConsumerEndpoint.cs b/src/TypedRest/Endpoints/Rpc/ConsumerEndpoint.cs index f52b2df9..ff5c1a9f 100644 --- a/src/TypedRest/Endpoints/Rpc/ConsumerEndpoint.cs +++ b/src/TypedRest/Endpoints/Rpc/ConsumerEndpoint.cs @@ -33,7 +33,7 @@ public Task InvokeAsync(TEntity entity, CancellationToken cancellationToken = de { if (entity == null) throw new ArgumentNullException(nameof(entity)); - return HandleResponseAsync(HttpClient.PostAsync(Uri, entity, Serializer, cancellationToken)); + return HandleAsync(() => HttpClient.PostAsync(Uri, entity, Serializer, cancellationToken)); } } } diff --git a/src/TypedRest/Endpoints/Rpc/FunctionEndpoint.cs b/src/TypedRest/Endpoints/Rpc/FunctionEndpoint.cs index 399e2865..40eca3c4 100644 --- a/src/TypedRest/Endpoints/Rpc/FunctionEndpoint.cs +++ b/src/TypedRest/Endpoints/Rpc/FunctionEndpoint.cs @@ -36,7 +36,7 @@ public async Task InvokeAsync(TEntity entity, CancellationToken cancell { if (entity == null) throw new ArgumentNullException(nameof(entity)); - var response = await HandleResponseAsync(HttpClient.PostAsync(Uri, entity, Serializer, cancellationToken)); + var response = await HandleAsync(() => HttpClient.PostAsync(Uri, entity, Serializer, cancellationToken)); return await response.Content.ReadAsAsync(Serializer, cancellationToken); } diff --git a/src/TypedRest/Endpoints/Rpc/ProducerEndpoint.cs b/src/TypedRest/Endpoints/Rpc/ProducerEndpoint.cs index 0bc6b1f7..0f9153e9 100644 --- a/src/TypedRest/Endpoints/Rpc/ProducerEndpoint.cs +++ b/src/TypedRest/Endpoints/Rpc/ProducerEndpoint.cs @@ -33,7 +33,7 @@ public ProducerEndpoint(IEndpoint referrer, string relativeUri) public async ITask InvokeAsync(CancellationToken cancellationToken = default) { - var response = await HandleResponseAsync(HttpClient.SendAsync(new HttpRequestMessage(HttpMethod.Post, Uri), cancellationToken)); + var response = await HandleAsync(() => HttpClient.SendAsync(new HttpRequestMessage(HttpMethod.Post, Uri), cancellationToken)); return await response.Content.ReadAsAsync(Serializer, cancellationToken); } diff --git a/src/TypedRest/Endpoints/Rpc/RpcEndpointBase.cs b/src/TypedRest/Endpoints/Rpc/RpcEndpointBase.cs index c564c6df..b6c7079b 100644 --- a/src/TypedRest/Endpoints/Rpc/RpcEndpointBase.cs +++ b/src/TypedRest/Endpoints/Rpc/RpcEndpointBase.cs @@ -30,7 +30,7 @@ protected RpcEndpointBase(IEndpoint referrer, string relativeUri) {} public Task ProbeAsync(CancellationToken cancellationToken = default) - => HandleResponseAsync(HttpClient.OptionsAsync(Uri, cancellationToken)); + => HandleAsync(() => HttpClient.OptionsAsync(Uri, cancellationToken)); public bool? InvokeAllowed => IsMethodAllowed(HttpMethod.Post); } diff --git a/src/UnitTests/Endpoints/CustomEndpointTest.cs b/src/UnitTests/Endpoints/CustomEndpointTest.cs index 1ae80efe..d530456d 100644 --- a/src/UnitTests/Endpoints/CustomEndpointTest.cs +++ b/src/UnitTests/Endpoints/CustomEndpointTest.cs @@ -285,7 +285,7 @@ public CustomEndpoint(IEndpoint referrer, string relativeUri) : base(referrer, relativeUri) {} - public Task GetAsync() => HandleResponseAsync(HttpClient.GetAsync(Uri)); + public Task GetAsync() => HandleAsync(() => HttpClient.GetAsync(Uri)); public new bool? IsMethodAllowed(HttpMethod method) => base.IsMethodAllowed(method); }