From f32226ddb4d012925f63536e1e9c0bd3c7afa521 Mon Sep 17 00:00:00 2001 From: yu_xianglong <87717663@qq.com> Date: Wed, 30 Oct 2024 21:08:45 +0800 Subject: [PATCH 1/3] feat:https://github.com/abpframework/abp/issues/21205 --- .../AbpHttpClientExecuteHttpActionOptions.cs | 12 ++++++++++++ .../Http/Client/ClientProxying/ClientProxyBase.cs | 8 +++++++- .../Volo/Abp/Http/AbpHttpClientTestModule.cs | 15 ++++++++++++++- .../DynamicProxying/IRegularTestController.cs | 3 +++ .../Http/DynamicProxying/RegularTestController.cs | 8 ++++++++ .../RegularTestControllerClientProxy_Tests.cs | 12 ++++++++++++ 6 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientExecuteHttpActionOptions.cs diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientExecuteHttpActionOptions.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientExecuteHttpActionOptions.cs new file mode 100644 index 0000000000..65e1613c7a --- /dev/null +++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientExecuteHttpActionOptions.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Reflection; +using System.Text; +using Volo.Abp.Http.Modeling; + +namespace Volo.Abp.Http.Client; +public class AbpHttpClientExecuteHttpActionOptions +{ + public Action? ExecuteHttpAction{ get; set; } +} diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyBase.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyBase.cs index a4306050a4..a1f847f10f 100644 --- a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyBase.cs +++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyBase.cs @@ -7,6 +7,7 @@ using System.Net.Http.Headers; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; +using Castle.DynamicProxy; using Microsoft.Extensions.Options; using Microsoft.Extensions.Primitives; using Volo.Abp.Content; @@ -43,6 +44,8 @@ public class ClientProxyBase : ITransientDependency protected ICurrentApiVersionInfo CurrentApiVersionInfo => LazyServiceProvider.LazyGetRequiredService(); protected ILocalEventBus LocalEventBus => LazyServiceProvider.LazyGetRequiredService(); + protected IOptions ExecuteHttpActionOptions => LazyServiceProvider.LazyGetRequiredService>(); + protected virtual async Task RequestAsync(string methodName, ClientProxyRequestTypeValue? arguments = null) { await RequestAsync(BuildHttpProxyClientProxyContext(methodName, arguments)); @@ -145,7 +148,10 @@ public class ClientProxyBase : ITransientDependency HttpResponseMessage response; try - { + { + //Allows users to customize the timeout for remote methods of specific requests + ExecuteHttpActionOptions.Value.ExecuteHttpAction?.Invoke(requestContext.Action, client); + response = await client.SendAsync( requestMessage, HttpCompletionOption.ResponseHeadersRead /*this will buffer only the headers, the content will be used as a stream*/, diff --git a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/AbpHttpClientTestModule.cs b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/AbpHttpClientTestModule.cs index 5e9107a23b..0da4d482dc 100644 --- a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/AbpHttpClientTestModule.cs +++ b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/AbpHttpClientTestModule.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.AspNetCore.Mvc; using Volo.Abp.Http.Client; @@ -60,5 +61,17 @@ public class AbpHttpClientTestModule : AbpModule options.FormDataConverts.Add(typeof(List), typeof(TestObjectToFormData)); options.PathConverts.Add(typeof(int), typeof(TestObjectToPath)); }); + + Configure(options => + { + options.ExecuteHttpAction = (method, httpclient) => + { + if (method.Name.Equals("TimeOutRequestAsync")) + { + httpclient.Timeout = TimeSpan.FromMilliseconds(2000); + } + }; + }); + } } diff --git a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/IRegularTestController.cs b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/IRegularTestController.cs index 547f1bf5a7..21786155bf 100644 --- a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/IRegularTestController.cs +++ b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/IRegularTestController.cs @@ -43,4 +43,7 @@ public interface IRegularTestController Task DeleteByIdAsync(int id); Task AbortRequestAsync(CancellationToken cancellationToken = default); + + Task TimeOutRequestAsync(); + } diff --git a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestController.cs b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestController.cs index b092e67bc8..c353f73e93 100644 --- a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestController.cs +++ b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestController.cs @@ -152,6 +152,14 @@ public class RegularTestController : AbpController, IRegularTestController await Task.Delay(100, cancellationToken); return "AbortRequestAsync"; } + + [HttpGet] + [Route("timeout-request")] + public async Task TimeOutRequestAsync() + { + await Task.Delay(5000); + return "timeout-request"; + } } public class Car diff --git a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestControllerClientProxy_Tests.cs b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestControllerClientProxy_Tests.cs index f094c756a9..4f095d468d 100644 --- a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestControllerClientProxy_Tests.cs +++ b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestControllerClientProxy_Tests.cs @@ -187,4 +187,16 @@ public class RegularTestControllerClientProxy_Tests : AbpHttpClientTestBase var exception = await Assert.ThrowsAsync(async () => await _controller.AbortRequestAsync(cts.Token)); exception.InnerException.InnerException.InnerException.Message.ShouldBe("The client aborted the request."); } + + [Fact] + public async Task TimeOutRequestAsync() + { + //This cannot be executed successfully because the unit test does not use SocketsHttpHandler for request processing, + //so the desired results cannot be obtained locally. At the same time, + //I can achieve the expected results by using other services locally. + + //var exception = await Assert.ThrowsAsync(async () => await _controller.TimeOutRequestAsync()); + //exception.InnerException.InnerException.InnerException.Message.ShouldBe("The client aborted the request."); + await Task.CompletedTask; + } } From ef871a44b6c72d74357a1c3893629ccaa7fc5337 Mon Sep 17 00:00:00 2001 From: maliming Date: Wed, 27 Nov 2024 13:49:11 +0800 Subject: [PATCH 2/3] Move `ExecuteHttpAction` to `AbpHttpClientOptions` and fix the unit test. --- .../Client/AbpHttpClientExecuteHttpActionOptions.cs | 12 ------------ .../Volo/Abp/Http/Client/AbpHttpClientOptions.cs | 5 +++++ .../Http/Client/ClientProxying/ClientProxyBase.cs | 11 +++++------ .../Volo/Abp/Http/AbpHttpClientTestModule.cs | 13 ++++++------- .../Http/DynamicProxying/RegularTestController.cs | 4 ++-- .../RegularTestControllerClientProxy_Tests.cs | 10 +++------- 6 files changed, 21 insertions(+), 34 deletions(-) delete mode 100644 framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientExecuteHttpActionOptions.cs diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientExecuteHttpActionOptions.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientExecuteHttpActionOptions.cs deleted file mode 100644 index 65e1613c7a..0000000000 --- a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientExecuteHttpActionOptions.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Net.Http; -using System.Reflection; -using System.Text; -using Volo.Abp.Http.Modeling; - -namespace Volo.Abp.Http.Client; -public class AbpHttpClientExecuteHttpActionOptions -{ - public Action? ExecuteHttpAction{ get; set; } -} diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientOptions.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientOptions.cs index 6743ab5174..0311423504 100644 --- a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientOptions.cs +++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientOptions.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using System.Net.Http; +using Volo.Abp.Http.Client.ClientProxying; using Volo.Abp.Http.Client.Proxying; namespace Volo.Abp.Http.Client; @@ -8,8 +10,11 @@ public class AbpHttpClientOptions { public Dictionary HttpClientProxies { get; set; } + public Dictionary> ProxyHttpClientPreSendActions { get; } + public AbpHttpClientOptions() { HttpClientProxies = new Dictionary(); + ProxyHttpClientPreSendActions = new Dictionary>(); } } diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyBase.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyBase.cs index a1f847f10f..9036b552f9 100644 --- a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyBase.cs +++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyBase.cs @@ -7,7 +7,6 @@ using System.Net.Http.Headers; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; -using Castle.DynamicProxy; using Microsoft.Extensions.Options; using Microsoft.Extensions.Primitives; using Volo.Abp.Content; @@ -44,8 +43,6 @@ public class ClientProxyBase : ITransientDependency protected ICurrentApiVersionInfo CurrentApiVersionInfo => LazyServiceProvider.LazyGetRequiredService(); protected ILocalEventBus LocalEventBus => LazyServiceProvider.LazyGetRequiredService(); - protected IOptions ExecuteHttpActionOptions => LazyServiceProvider.LazyGetRequiredService>(); - protected virtual async Task RequestAsync(string methodName, ClientProxyRequestTypeValue? arguments = null) { await RequestAsync(BuildHttpProxyClientProxyContext(methodName, arguments)); @@ -148,9 +145,11 @@ public class ClientProxyBase : ITransientDependency HttpResponseMessage response; try - { - //Allows users to customize the timeout for remote methods of specific requests - ExecuteHttpActionOptions.Value.ExecuteHttpAction?.Invoke(requestContext.Action, client); + { + foreach (var preSendAction in ClientOptions.Value.ProxyHttpClientPreSendActions.Where(x => x.Key == clientConfig.RemoteServiceName).Select(x => x.Value)) + { + preSendAction(clientConfig, requestContext, client); + } response = await client.SendAsync( requestMessage, diff --git a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/AbpHttpClientTestModule.cs b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/AbpHttpClientTestModule.cs index 0da4d482dc..8af7a5bbbe 100644 --- a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/AbpHttpClientTestModule.cs +++ b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/AbpHttpClientTestModule.cs @@ -62,16 +62,15 @@ public class AbpHttpClientTestModule : AbpModule options.PathConverts.Add(typeof(int), typeof(TestObjectToPath)); }); - Configure(options => + Configure(options => { - options.ExecuteHttpAction = (method, httpclient) => + options.ProxyHttpClientPreSendActions.Add("Default", (_, requestContext, httpclient) => { - if (method.Name.Equals("TimeOutRequestAsync")) - { - httpclient.Timeout = TimeSpan.FromMilliseconds(2000); + if (requestContext.Action.Name.Equals("TimeOutRequestAsync")) + { + httpclient.Timeout = TimeSpan.FromMilliseconds(1); } - }; + }); }); - } } diff --git a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestController.cs b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestController.cs index c353f73e93..46b355090b 100644 --- a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestController.cs +++ b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestController.cs @@ -157,8 +157,8 @@ public class RegularTestController : AbpController, IRegularTestController [Route("timeout-request")] public async Task TimeOutRequestAsync() { - await Task.Delay(5000); - return "timeout-request"; + await Task.Delay(100); + return "TimeOutRequestAsync"; } } diff --git a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestControllerClientProxy_Tests.cs b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestControllerClientProxy_Tests.cs index 4f095d468d..01ec97d734 100644 --- a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestControllerClientProxy_Tests.cs +++ b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestControllerClientProxy_Tests.cs @@ -1,4 +1,5 @@ using System; +using System.Net.Http; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; @@ -191,12 +192,7 @@ public class RegularTestControllerClientProxy_Tests : AbpHttpClientTestBase [Fact] public async Task TimeOutRequestAsync() { - //This cannot be executed successfully because the unit test does not use SocketsHttpHandler for request processing, - //so the desired results cannot be obtained locally. At the same time, - //I can achieve the expected results by using other services locally. - - //var exception = await Assert.ThrowsAsync(async () => await _controller.TimeOutRequestAsync()); - //exception.InnerException.InnerException.InnerException.Message.ShouldBe("The client aborted the request."); - await Task.CompletedTask; + var exception = await Assert.ThrowsAsync(async () => await _controller.TimeOutRequestAsync()); + exception.InnerException.InnerException.Message.ShouldBe("The client aborted the request."); } } From ae5980207d2250644cf2c7c02c5f1cf11476bab3 Mon Sep 17 00:00:00 2001 From: maliming Date: Wed, 27 Nov 2024 14:11:38 +0800 Subject: [PATCH 3/3] Support multiple `PreActions`. --- .../Volo/Abp/Http/Client/AbpHttpClientOptions.cs | 10 ++++++++-- .../Abp/Http/Client/ClientProxying/ClientProxyBase.cs | 2 +- .../Volo/Abp/Http/AbpHttpClientTestModule.cs | 4 +++- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientOptions.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientOptions.cs index 0311423504..bfe52508e4 100644 --- a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientOptions.cs +++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientOptions.cs @@ -10,11 +10,17 @@ public class AbpHttpClientOptions { public Dictionary HttpClientProxies { get; set; } - public Dictionary> ProxyHttpClientPreSendActions { get; } + public Dictionary>> ProxyHttpClientPreSendActions { get; } public AbpHttpClientOptions() { HttpClientProxies = new Dictionary(); - ProxyHttpClientPreSendActions = new Dictionary>(); + ProxyHttpClientPreSendActions = new Dictionary>>(); + } + + public AbpHttpClientOptions AddPreSendAction(string remoteServiceName, Action action) + { + ProxyHttpClientPreSendActions.GetOrAdd(remoteServiceName, () => new List>()).Add(action); + return this; } } diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyBase.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyBase.cs index 9036b552f9..68664ca513 100644 --- a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyBase.cs +++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyBase.cs @@ -146,7 +146,7 @@ public class ClientProxyBase : ITransientDependency HttpResponseMessage response; try { - foreach (var preSendAction in ClientOptions.Value.ProxyHttpClientPreSendActions.Where(x => x.Key == clientConfig.RemoteServiceName).Select(x => x.Value)) + foreach (var preSendAction in ClientOptions.Value.ProxyHttpClientPreSendActions.Where(x => x.Key == clientConfig.RemoteServiceName).SelectMany(x => x.Value)) { preSendAction(clientConfig, requestContext, client); } diff --git a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/AbpHttpClientTestModule.cs b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/AbpHttpClientTestModule.cs index 8af7a5bbbe..4dd69041fc 100644 --- a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/AbpHttpClientTestModule.cs +++ b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/AbpHttpClientTestModule.cs @@ -1,9 +1,11 @@ using System; using System.Collections.Generic; +using System.Net.Http; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.AspNetCore.Mvc; using Volo.Abp.Http.Client; using Volo.Abp.Http.Client.ClientProxying; +using Volo.Abp.Http.Client.Proxying; using Volo.Abp.Http.DynamicProxying; using Volo.Abp.Http.Localization; using Volo.Abp.Localization; @@ -64,7 +66,7 @@ public class AbpHttpClientTestModule : AbpModule Configure(options => { - options.ProxyHttpClientPreSendActions.Add("Default", (_, requestContext, httpclient) => + options.AddPreSendAction("Default", (_, requestContext, httpclient) => { if (requestContext.Action.Name.Equals("TimeOutRequestAsync")) {