From 396318fe0b6a7f8391ba91e2f0b22af3d06c7bdc Mon Sep 17 00:00:00 2001 From: Albie Date: Sat, 2 Jul 2022 17:20:27 +0100 Subject: [PATCH 1/7] create callback interfaces --- .../IAsyncRequestExecutingCallback.cs | 20 +++++++++++++++++++ src/Requests/IRequestExecutingCallback.cs | 16 +++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 src/Requests/IAsyncRequestExecutingCallback.cs create mode 100644 src/Requests/IRequestExecutingCallback.cs diff --git a/src/Requests/IAsyncRequestExecutingCallback.cs b/src/Requests/IAsyncRequestExecutingCallback.cs new file mode 100644 index 0000000..4d7431b --- /dev/null +++ b/src/Requests/IAsyncRequestExecutingCallback.cs @@ -0,0 +1,20 @@ +// DragonFruit.Data Copyright DragonFruit Network +// Licensed under the MIT License. Please refer to the LICENSE file at the root of this project for details + +using System.Net.Http; +using System.Threading.Tasks; + +namespace DragonFruit.Data.Requests +{ + /// + /// Specifies the should have its method called after when the request is being executed + /// + public interface IAsyncRequestExecutingCallback + { + /// + /// Overridable method for specifying an action to occur before sending the request to the . + /// Unlike , this will be run asynchronously and must return a . + /// + ValueTask OnRequestExecutingAsync(ApiClient client); + } +} diff --git a/src/Requests/IRequestExecutingCallback.cs b/src/Requests/IRequestExecutingCallback.cs new file mode 100644 index 0000000..6bb3f79 --- /dev/null +++ b/src/Requests/IRequestExecutingCallback.cs @@ -0,0 +1,16 @@ +// DragonFruit.Data Copyright DragonFruit Network +// Licensed under the MIT License. Please refer to the LICENSE file at the root of this project for details + +namespace DragonFruit.Data.Requests +{ + /// + /// Specifies the should have its method called after when the request is being executed + /// + public interface IRequestExecutingCallback + { + /// + /// Overridable method for specifying an action to occur before sending the request to the + /// + void OnRequestExecuting(ApiClient client); + } +} From 2d2fcec678ccf95b274215de335b4197302aa75a Mon Sep 17 00:00:00 2001 From: Albie Date: Sat, 2 Jul 2022 17:20:39 +0100 Subject: [PATCH 2/7] remove old override --- src/ApiRequest.cs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/ApiRequest.cs b/src/ApiRequest.cs index ea41e85..1e0ccf5 100644 --- a/src/ApiRequest.cs +++ b/src/ApiRequest.cs @@ -98,13 +98,6 @@ internal string QueryString /// protected virtual IEnumerable> AdditionalQueries { get; } - /// - /// Overridable method for specifying an action to occur before sending the request to the - /// - protected internal virtual void OnRequestExecuting(ApiClient client) - { - } - /// /// Create a for this , which can then be modified manually or overriden by /// From e3bf9d41c400f7215e7709dcc87f5e8620510df6 Mon Sep 17 00:00:00 2001 From: Albie Date: Sat, 2 Jul 2022 17:21:04 +0100 Subject: [PATCH 3/7] add type checks to validaterequest --- src/ApiClient.cs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/ApiClient.cs b/src/ApiClient.cs index 688f3f7..7b384b9 100644 --- a/src/ApiClient.cs +++ b/src/ApiClient.cs @@ -10,6 +10,7 @@ using System.Xml; using DragonFruit.Data.Exceptions; using DragonFruit.Data.Headers; +using DragonFruit.Data.Requests; using DragonFruit.Data.Serializers; using DragonFruit.Data.Utils; using Nito.AsyncEx; @@ -166,9 +167,17 @@ protected virtual async Task ValidateAndProcess(HttpResponseMessage respon /// The request to validate /// The request can't be performed due to a poorly-formed url /// The client can't be used because there is no auth url. - protected virtual void ValidateRequest(ApiRequest request) + protected virtual async Task ValidateRequest(ApiRequest request) { - request.OnRequestExecuting(this); + if (request is IRequestExecutingCallback syncCallback) + { + syncCallback.OnRequestExecuting(this); + } + + if (request is IAsyncRequestExecutingCallback asyncCallback) + { + await asyncCallback.OnRequestExecutingAsync(this).ConfigureAwait(false); + } // note request path is validated on build if (request.RequireAuth && string.IsNullOrEmpty(Authorization)) @@ -262,7 +271,7 @@ public Func Handler /// /// /// This should be used when a library needs to enforce a is wrapped over the . - /// If overriden, it should be sealed to prevent misuse + /// If overriden, the client should be sealed to prevent unintended changes /// protected virtual HttpMessageHandler CreateHandler() => Handler?.Invoke(); From c2bc3fa776196f0d6d10b94d65e35291de6075b7 Mon Sep 17 00:00:00 2001 From: Albie Date: Sat, 2 Jul 2022 17:21:19 +0100 Subject: [PATCH 4/7] await request validation when async --- src/ApiClient_Async.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/ApiClient_Async.cs b/src/ApiClient_Async.cs index 0426bb8..e2390ab 100644 --- a/src/ApiClient_Async.cs +++ b/src/ApiClient_Async.cs @@ -25,10 +25,10 @@ public Task PerformAsync(string url, CancellationToken token = default) wh /// /// Perform an with a specified return type. /// - public Task PerformAsync(ApiRequest requestData, CancellationToken token = default) where T : class + public async Task PerformAsync(ApiRequest requestData, CancellationToken token = default) where T : class { - ValidateRequest(requestData); - return PerformAsync(requestData.Build(this), token); + await ValidateRequest(requestData).ConfigureAwait(false); + return await PerformAsync(requestData.Build(this), token).ConfigureAwait(false); } /// @@ -51,10 +51,10 @@ public Task PerformAsync(string url, CancellationToken toke /// /// Perform a that returns the response message. /// - public Task PerformAsync(ApiRequest requestData, CancellationToken token = default) + public async Task PerformAsync(ApiRequest requestData, CancellationToken token = default) { - ValidateRequest(requestData); - return PerformAsync(requestData.Build(this), token); + await ValidateRequest(requestData).ConfigureAwait(false); + return await PerformAsync(requestData.Build(this), token).ConfigureAwait(false); } /// @@ -74,7 +74,7 @@ public Task PerformAsync(HttpRequestMessage request, Cancel public async Task PerformAsync(ApiFileRequest request, Action progressUpdated = null, CancellationToken token = default) { // check request data is valid - ValidateRequest(request); + await ValidateRequest(request).ConfigureAwait(false); if (string.IsNullOrWhiteSpace(request.Destination)) { From 37acffb369f47f8bd58bdcd867283debe0616f3e Mon Sep 17 00:00:00 2001 From: Albie Date: Sat, 2 Jul 2022 17:21:25 +0100 Subject: [PATCH 5/7] update tests --- tests/Requests/RequestFilterTests.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/Requests/RequestFilterTests.cs b/tests/Requests/RequestFilterTests.cs index 02e186e..f679b69 100644 --- a/tests/Requests/RequestFilterTests.cs +++ b/tests/Requests/RequestFilterTests.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. Please refer to the LICENSE file at the root of this project for details using System; +using DragonFruit.Data.Requests; using NUnit.Framework; namespace DragonFruit.Data.Tests.Requests @@ -16,11 +17,11 @@ public void TestFilteredRequests() Assert.Catch(() => Client.Perform(new InheritedRequest())); } - internal class FilteredRequest : ApiRequest + internal class FilteredRequest : ApiRequest, IRequestExecutingCallback { public override string Path { get; } - protected override void OnRequestExecuting(ApiClient client) + void IRequestExecutingCallback.OnRequestExecuting(ApiClient client) { throw new ArgumentException(); } From 1b06b7f48fdb74ca5b842fcd57a19178a9ebed7b Mon Sep 17 00:00:00 2001 From: Albie Date: Sat, 2 Jul 2022 17:23:19 +0100 Subject: [PATCH 6/7] remove redundant comments --- src/ApiClient.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/ApiClient.cs b/src/ApiClient.cs index 7b384b9..bdf54b2 100644 --- a/src/ApiClient.cs +++ b/src/ApiClient.cs @@ -123,7 +123,6 @@ protected async Task InternalPerform(HttpRequestMessage request, Func InternalPerform(HttpRequestMessage request, Func Date: Sat, 2 Jul 2022 17:30:33 +0100 Subject: [PATCH 7/7] fix unit tests --- tests/Requests/RequestFilterTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Requests/RequestFilterTests.cs b/tests/Requests/RequestFilterTests.cs index f679b69..4417de5 100644 --- a/tests/Requests/RequestFilterTests.cs +++ b/tests/Requests/RequestFilterTests.cs @@ -13,8 +13,8 @@ public class RequestFilterTests : ApiTest [Test] public void TestFilteredRequests() { - Assert.Catch(() => Client.Perform(new FilteredRequest())); - Assert.Catch(() => Client.Perform(new InheritedRequest())); + Assert.Catch(() => Client.Perform(new FilteredRequest())); + Assert.CatchAsync(() => Client.PerformAsync(new InheritedRequest())); } internal class FilteredRequest : ApiRequest, IRequestExecutingCallback