From 0bc8a4a2615af99dd3862167ff5b7e4c02cc2c11 Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 21 Oct 2021 12:22:53 +0800 Subject: [PATCH 1/4] Enhance the error that occurs during the http request. --- .../DefaultExceptionToErrorInfoConverter.cs | 6 +++--- .../Abp/Http/Client/AbpRemoteCallException.cs | 9 ++++++++- .../Client/ClientProxying/ClientProxyBase.cs | 19 ++++++++++++++----- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs index a96797ce40..abe0f3ab84 100644 --- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs +++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs @@ -42,7 +42,7 @@ namespace Volo.Abp.AspNetCore.ExceptionHandling { var errorInfo = CreateErrorInfoWithoutCode(exception, includeSensitiveDetails); - if (exception is IHasErrorCode hasErrorCodeException) + if (exception is IHasErrorCode hasErrorCodeException && hasErrorCodeException.Code.IsNullOrWhiteSpace()) { errorInfo.Code = hasErrorCodeException.Code; } @@ -61,7 +61,7 @@ namespace Volo.Abp.AspNetCore.ExceptionHandling if (exception is AbpRemoteCallException remoteCallException) { - return remoteCallException.Error; + return remoteCallException.Error ?? new RemoteServiceErrorInfo(remoteCallException.Message); } if (exception is AbpDbConcurrencyException) @@ -175,7 +175,7 @@ namespace Volo.Abp.AspNetCore.ExceptionHandling return new RemoteServiceErrorInfo(exception.Message); } - + protected virtual Exception TryToGetActualException(Exception exception) { if (exception is AggregateException && exception.InnerException != null) diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/Http/Client/AbpRemoteCallException.cs b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/Http/Client/AbpRemoteCallException.cs index f9a6436715..4feb2d2d82 100644 --- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/Http/Client/AbpRemoteCallException.cs +++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/Http/Client/AbpRemoteCallException.cs @@ -15,7 +15,14 @@ namespace Volo.Abp.Http.Client public RemoteServiceErrorInfo Error { get; set; } - public AbpRemoteCallException() + public AbpRemoteCallException(string message) + : base(message) + { + + } + + public AbpRemoteCallException(string message, Exception innerException) + : base(message, innerException) { } 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 73e51080c6..a5da68b7b0 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 @@ -132,11 +132,20 @@ namespace Volo.Abp.Http.Client.ClientProxying ); } - var response = await client.SendAsync( - requestMessage, - HttpCompletionOption.ResponseHeadersRead /*this will buffer only the headers, the content will be used as a stream*/, - GetCancellationToken(requestContext.Arguments) - ); + HttpResponseMessage response; + try + { + response = await client.SendAsync( + requestMessage, + HttpCompletionOption + .ResponseHeadersRead /*this will buffer only the headers, the content will be used as a stream*/, + GetCancellationToken(requestContext.Arguments) + ); + } + catch (Exception ex) + { + throw new AbpRemoteCallException($"An error occurred during the ABP remote HTTP request. ({ex.Message}) See the inner exception for details.", ex); + } if (!response.IsSuccessStatusCode) { From 8b629468eea8c3a8e5def53fe6b1cf5aa5d1960a Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 21 Oct 2021 14:10:28 +0800 Subject: [PATCH 2/4] Add `RegularTestControllerClientProxy_AbpRemoteCallException_Tests` --- .../DefaultExceptionToErrorInfoConverter.cs | 6 +- .../Abp/Http/Client/AbpRemoteCallException.cs | 4 +- .../Client/ClientProxying/ClientProxyBase.cs | 52 +++++++++++----- ...lientProxy_AbpRemoteCallException_Tests.cs | 61 +++++++++++++++++++ .../RegularTestControllerClientProxy_Tests.cs | 4 +- 5 files changed, 105 insertions(+), 22 deletions(-) create mode 100644 framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestControllerClientProxy_AbpRemoteCallException_Tests.cs diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs index abe0f3ab84..16fae96db6 100644 --- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs +++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs @@ -59,9 +59,9 @@ namespace Volo.Abp.AspNetCore.ExceptionHandling exception = TryToGetActualException(exception); - if (exception is AbpRemoteCallException remoteCallException) + if (exception is AbpRemoteCallException remoteCallException && remoteCallException.Error != null) { - return remoteCallException.Error ?? new RemoteServiceErrorInfo(remoteCallException.Message); + return remoteCallException.Error; } if (exception is AbpDbConcurrencyException) @@ -76,7 +76,7 @@ namespace Volo.Abp.AspNetCore.ExceptionHandling var errorInfo = new RemoteServiceErrorInfo(); - if (exception is IUserFriendlyException) + if (exception is IUserFriendlyException || exception is AbpRemoteCallException) { errorInfo.Message = exception.Message; errorInfo.Details = (exception as IHasErrorDetails)?.Details; diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/Http/Client/AbpRemoteCallException.cs b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/Http/Client/AbpRemoteCallException.cs index 4feb2d2d82..43fb00b03a 100644 --- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/Http/Client/AbpRemoteCallException.cs +++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/Http/Client/AbpRemoteCallException.cs @@ -33,8 +33,8 @@ namespace Volo.Abp.Http.Client } - public AbpRemoteCallException(RemoteServiceErrorInfo error) - : base(error.Message) + public AbpRemoteCallException(RemoteServiceErrorInfo error, Exception innerException = null) + : base(error.Message, innerException) { Error = error; 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 a5da68b7b0..984a1aa3e1 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 @@ -6,6 +6,8 @@ using System.Net.Http; using System.Net.Http.Headers; using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; using Microsoft.Extensions.Primitives; using Volo.Abp.Content; @@ -26,6 +28,7 @@ namespace Volo.Abp.Http.Client.ClientProxying { public IAbpLazyServiceProvider LazyServiceProvider { get; set; } + protected ILogger> Logger => LazyServiceProvider.LazyGetService>>(NullLogger>.Instance); protected IClientProxyApiDescriptionFinder ClientProxyApiDescriptionFinder => LazyServiceProvider.LazyGetRequiredService(); protected ICancellationTokenProvider CancellationTokenProvider => LazyServiceProvider.LazyGetRequiredService(); protected ICorrelationIdProvider CorrelationIdProvider => LazyServiceProvider.LazyGetRequiredService(); @@ -137,8 +140,7 @@ namespace Volo.Abp.Http.Client.ClientProxying { response = await client.SendAsync( requestMessage, - HttpCompletionOption - .ResponseHeadersRead /*this will buffer only the headers, the content will be used as a stream*/, + HttpCompletionOption.ResponseHeadersRead /*this will buffer only the headers, the content will be used as a stream*/, GetCancellationToken(requestContext.Arguments) ); } @@ -206,26 +208,46 @@ namespace Volo.Abp.Http.Client.ClientProxying { if (response.Headers.Contains(AbpHttpConsts.AbpErrorFormat)) { - var errorResponse = JsonSerializer.Deserialize( - await response.Content.ReadAsStringAsync() - ); + RemoteServiceErrorResponse errorResponse; + try + { + errorResponse = JsonSerializer.Deserialize( + await response.Content.ReadAsStringAsync() + ); + } + catch (Exception ex) + { + throw new AbpRemoteCallException( + new RemoteServiceErrorInfo + { + Message = response.ReasonPhrase, + Code = response.StatusCode.ToString() + }, + ex + ) + { + HttpStatusCode = (int)response.StatusCode + }; + } throw new AbpRemoteCallException(errorResponse.Error) { HttpStatusCode = (int) response.StatusCode }; } - - throw new AbpRemoteCallException( - new RemoteServiceErrorInfo - { - Message = response.ReasonPhrase, - Code = response.StatusCode.ToString() - } - ) + else { - HttpStatusCode = (int) response.StatusCode - }; + throw new AbpRemoteCallException( + new RemoteServiceErrorInfo + { + Message = response.ReasonPhrase, + Code = response.StatusCode.ToString() + } + ) + { + HttpStatusCode = (int) response.StatusCode + }; + } } protected virtual void AddHeaders( diff --git a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestControllerClientProxy_AbpRemoteCallException_Tests.cs b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestControllerClientProxy_AbpRemoteCallException_Tests.cs new file mode 100644 index 0000000000..77f126cf5e --- /dev/null +++ b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestControllerClientProxy_AbpRemoteCallException_Tests.cs @@ -0,0 +1,61 @@ +using System.Net.Http; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Hosting; +using Shouldly; +using Volo.Abp.AspNetCore.TestBase; +using Volo.Abp.Http.Client; +using Volo.Abp.Http.Client.Proxying; +using Xunit; + +namespace Volo.Abp.Http.DynamicProxying +{ + public class RegularTestControllerClientProxy_AbpRemoteCallException_Tests : AbpHttpClientTestBase + { + private readonly IRegularTestController _controller; + + public RegularTestControllerClientProxy_AbpRemoteCallException_Tests() + { + _controller = ServiceProvider.GetRequiredService(); + } + + protected override void ConfigureServices(HostBuilderContext context, IServiceCollection services) + { + services.Replace(ServiceDescriptor.Singleton()); + } + + [Fact] + public async Task AbpRemoteCallException_On_SendAsync_Test() + { + var exception = await Assert.ThrowsAsync(async () => await _controller.AbortRequestAsync(default)); + exception.Message.ShouldContain("An error occurred during the ABP remote HTTP request."); + } + + class TestProxyHttpClientFactory : IProxyHttpClientFactory + { + private readonly ITestServerAccessor _testServerAccessor; + + private int _count; + + public TestProxyHttpClientFactory(ITestServerAccessor testServerAccessor) + { + _testServerAccessor = testServerAccessor; + } + + public HttpClient Create(string name) => Create(); + + public HttpClient Create() + { + if (_count++ > 0) + { + //Will get an error on the SendAsync method. + return new HttpClient(); + } + + // for DynamicHttpProxyInterceptor.GetActionApiDescriptionModel + return _testServerAccessor.Server.CreateClient(); + } + } + } +} 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 8df3e94b3c..c1c46b298f 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 @@ -168,8 +168,8 @@ namespace Volo.Abp.Http.DynamicProxying var result = await _controller.AbortRequestAsync(default); result.ShouldBe("AbortRequestAsync"); - var exception = await Assert.ThrowsAsync(async () => await _controller.AbortRequestAsync(cts.Token)); - exception.InnerException.InnerException.Message.ShouldBe("The client aborted the request."); + var exception = await Assert.ThrowsAsync(async () => await _controller.AbortRequestAsync(cts.Token)); + exception.InnerException.InnerException.InnerException.Message.ShouldBe("The client aborted the request."); } } } From 9dec319c2ca535b3877d28efdbee7b8905c423bd Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 21 Oct 2021 14:17:25 +0800 Subject: [PATCH 3/4] Reduce some code. --- .../DefaultExceptionToErrorInfoConverter.cs | 2 +- .../Volo/Abp/Http/Client/AbpRemoteCallException.cs | 8 +------- .../Abp/Http/Client/ClientProxying/ClientProxyBase.cs | 3 --- 3 files changed, 2 insertions(+), 11 deletions(-) diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs index 16fae96db6..eeddb2e9be 100644 --- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs +++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs @@ -42,7 +42,7 @@ namespace Volo.Abp.AspNetCore.ExceptionHandling { var errorInfo = CreateErrorInfoWithoutCode(exception, includeSensitiveDetails); - if (exception is IHasErrorCode hasErrorCodeException && hasErrorCodeException.Code.IsNullOrWhiteSpace()) + if (exception is IHasErrorCode hasErrorCodeException) { errorInfo.Code = hasErrorCodeException.Code; } diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/Http/Client/AbpRemoteCallException.cs b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/Http/Client/AbpRemoteCallException.cs index 43fb00b03a..cd438685a3 100644 --- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/Http/Client/AbpRemoteCallException.cs +++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/Http/Client/AbpRemoteCallException.cs @@ -15,13 +15,7 @@ namespace Volo.Abp.Http.Client public RemoteServiceErrorInfo Error { get; set; } - public AbpRemoteCallException(string message) - : base(message) - { - - } - - public AbpRemoteCallException(string message, Exception innerException) + public AbpRemoteCallException(string message, Exception innerException = null) : base(message, innerException) { 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 984a1aa3e1..66dbe4f3cd 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 @@ -6,8 +6,6 @@ using System.Net.Http; using System.Net.Http.Headers; using System.Threading; using System.Threading.Tasks; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; using Microsoft.Extensions.Primitives; using Volo.Abp.Content; @@ -28,7 +26,6 @@ namespace Volo.Abp.Http.Client.ClientProxying { public IAbpLazyServiceProvider LazyServiceProvider { get; set; } - protected ILogger> Logger => LazyServiceProvider.LazyGetService>>(NullLogger>.Instance); protected IClientProxyApiDescriptionFinder ClientProxyApiDescriptionFinder => LazyServiceProvider.LazyGetRequiredService(); protected ICancellationTokenProvider CancellationTokenProvider => LazyServiceProvider.LazyGetRequiredService(); protected ICorrelationIdProvider CorrelationIdProvider => LazyServiceProvider.LazyGetRequiredService(); From a797ecb5b548ead42662df4751b874935a822ae7 Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 21 Oct 2021 14:20:59 +0800 Subject: [PATCH 4/4] Add an empty ctor. --- .../Volo/Abp/Http/Client/AbpRemoteCallException.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/Http/Client/AbpRemoteCallException.cs b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/Http/Client/AbpRemoteCallException.cs index cd438685a3..f561c4cab7 100644 --- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/Http/Client/AbpRemoteCallException.cs +++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/Http/Client/AbpRemoteCallException.cs @@ -15,6 +15,11 @@ namespace Volo.Abp.Http.Client public RemoteServiceErrorInfo Error { get; set; } + public AbpRemoteCallException() + { + + } + public AbpRemoteCallException(string message, Exception innerException = null) : base(message, innerException) {