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; + } }