diff --git a/src/Lykke.HttpClientGenerator/ApiExceptionTextExtensions.cs b/src/Lykke.HttpClientGenerator/ApiExceptionTextExtensions.cs new file mode 100644 index 0000000..2d54914 --- /dev/null +++ b/src/Lykke.HttpClientGenerator/ApiExceptionTextExtensions.cs @@ -0,0 +1,54 @@ +using Common; +using Refit; + +namespace Lykke.HttpClientGenerator +{ + /// + /// Text extensions for + /// + public static class ApiExceptionTextExtensions + { + /// + /// Get http request caused the exception as text + /// + /// + /// + public static string GetRequestPhrase(this ApiException exception) + { + return exception.RequestMessage == null ? string.Empty : $"Request: {exception.RequestMessage.ToJson()}."; + } + + /// + /// Get response content as text + /// + /// + /// + public static string GetContentPhrase(this ApiException exception) + { + return exception.HasContent ? $"Content: {exception.Content.ToJson()}." : string.Empty; + } + + /// + /// Get exception data as text + /// + /// + /// + public static string GetDataPhrase(this ApiException exception) + { + if (exception.Data.Count == 0) + return string.Empty; + + return $"Data: {exception.Data.ToJson()}."; + } + + /// + /// Get exception description including all the details about request and error, as text + /// + /// + /// + public static string GetDescription(this ApiException exception) + { + return $"Couldn't execute http request. Reason: {exception.ReasonPhrase}. {exception.GetContentPhrase()} {exception.GetDataPhrase()} {exception.GetRequestPhrase()}"; + } + } +} \ No newline at end of file diff --git a/src/Lykke.HttpClientGenerator/Exceptions/RefitExceptionHandlerMiddleware.cs b/src/Lykke.HttpClientGenerator/Exceptions/RefitExceptionHandlerMiddleware.cs new file mode 100644 index 0000000..29f4ba5 --- /dev/null +++ b/src/Lykke.HttpClientGenerator/Exceptions/RefitExceptionHandlerMiddleware.cs @@ -0,0 +1,60 @@ +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; +using Refit; + +namespace Lykke.HttpClientGenerator.Exceptions +{ + /// + /// Refit specific exceptions handling middleware + /// + public class RefitExceptionHandlerMiddleware + { + private readonly RequestDelegate _next; + private readonly RefitExceptionHandlingOptions _options; + private readonly ILogger _logger; + + /// + /// Creates middleware + /// + /// + /// + /// + public RefitExceptionHandlerMiddleware(RequestDelegate next, + ILogger logger, + RefitExceptionHandlingOptions options) + { + _next = next; + _logger = logger; + _options = options; + } + + /// + /// Executes upon middleware invocation + /// + /// + /// + public async Task Invoke(HttpContext context) + { + try + { + await _next(context); + } + catch (ValidationApiException e) + { + _logger.LogError(e, e.GetDescription()); + if (_options.ReThrow) throw; + } + catch (ApiException e) + { + _logger.LogError(e, e.GetDescription()); + if (_options.ReThrow) throw; + } + catch (HttpClientApiException e) + { + _logger.LogError(e, e.GetDescription()); + if (_options.ReThrow) throw; + } + } + } +} \ No newline at end of file diff --git a/src/Lykke.HttpClientGenerator/Exceptions/RefitExceptionHandlingOptions.cs b/src/Lykke.HttpClientGenerator/Exceptions/RefitExceptionHandlingOptions.cs new file mode 100644 index 0000000..a30bbf1 --- /dev/null +++ b/src/Lykke.HttpClientGenerator/Exceptions/RefitExceptionHandlingOptions.cs @@ -0,0 +1,13 @@ +namespace Lykke.HttpClientGenerator.Exceptions +{ + /// + /// Options for Refit exceptions handling middleware + /// + public class RefitExceptionHandlingOptions + { + /// + /// If exception has to be thrown after processing + /// + public bool ReThrow { get; set; } + } +} \ No newline at end of file diff --git a/src/Lykke.HttpClientGenerator/HttpClientApiExceptionTextExtensions.cs b/src/Lykke.HttpClientGenerator/HttpClientApiExceptionTextExtensions.cs new file mode 100644 index 0000000..9662c1f --- /dev/null +++ b/src/Lykke.HttpClientGenerator/HttpClientApiExceptionTextExtensions.cs @@ -0,0 +1,44 @@ +using Common; +using Lykke.HttpClientGenerator.Exceptions; + +namespace Lykke.HttpClientGenerator +{ + /// + /// Text extensions for + /// + public static class HttpClientApiExceptionTextExtensions + { + /// + /// Get error response as text + /// + /// + /// + public static string GetErrorResponsePhrase(this HttpClientApiException exception) + { + if (exception.ErrorResponse == null) + return string.Empty; + + return $"Error response: {exception.ErrorResponse.ToJson()}."; + } + + /// + /// Get status code as text + /// + /// + /// + public static string GetStatusCodePhrase(this HttpClientApiException exception) + { + return $"Status code: {exception.HttpStatusCode.ToString()}."; + } + + /// + /// Get exception description including all the details about error, as text + /// + /// + /// + public static string GetDescription(this HttpClientApiException exception) + { + return $"Couldn't execute http request. {GetErrorResponsePhrase(exception)} {GetStatusCodePhrase(exception)}"; + } + } +} \ No newline at end of file diff --git a/src/Lykke.HttpClientGenerator/Lykke.HttpClientGenerator.csproj b/src/Lykke.HttpClientGenerator/Lykke.HttpClientGenerator.csproj index 2903968..ea5b44e 100644 --- a/src/Lykke.HttpClientGenerator/Lykke.HttpClientGenerator.csproj +++ b/src/Lykke.HttpClientGenerator/Lykke.HttpClientGenerator.csproj @@ -20,7 +20,7 @@ - + \ No newline at end of file diff --git a/src/Lykke.HttpClientGenerator/ValidationApiExceptionTextExtensions.cs b/src/Lykke.HttpClientGenerator/ValidationApiExceptionTextExtensions.cs new file mode 100644 index 0000000..e08e4f2 --- /dev/null +++ b/src/Lykke.HttpClientGenerator/ValidationApiExceptionTextExtensions.cs @@ -0,0 +1,32 @@ +using Common; +using Lykke.HttpClientGenerator.Retries; +using Refit; + +namespace Lykke.HttpClientGenerator +{ + /// + /// Text extensions for + /// + public static class ValidationApiExceptionTextExtensions + { + /// + /// Get http request caused the exception problem details as text + /// + /// + /// + public static string GetProblemDetailsPhrase(this ValidationApiException exception) + { + return exception.HasContent ? $"Problem details: {exception.Content.ToJson()}." : string.Empty; + } + + /// + /// Get exception description including all the details about request and error, as text + /// + /// + /// + public static string GetDescription(this ValidationApiException exception) + { + return $"Couldn't execute http request. {exception.GetProblemDetailsPhrase()} {exception.GetRequestPhrase()}"; + } + } +} \ No newline at end of file diff --git a/tests/Lykke.HttpClientGenerator.Tests/CustomUrlParameterFormatterTests.cs b/tests/Lykke.HttpClientGenerator.Tests/CustomUrlParameterFormatterTests.cs index 62610a5..a7a8215 100644 --- a/tests/Lykke.HttpClientGenerator.Tests/CustomUrlParameterFormatterTests.cs +++ b/tests/Lykke.HttpClientGenerator.Tests/CustomUrlParameterFormatterTests.cs @@ -1,4 +1,5 @@ -using System.Net; +using System; +using System.Net; using System.Net.Http; using System.Reflection; using System.Threading.Tasks; @@ -87,7 +88,7 @@ public SuffixUrlParameterFormatter(string suffix) _suffix = suffix ?? string.Empty; } - public string Format(object value, ParameterInfo parameterInfo) + public string Format(object value, ICustomAttributeProvider attributeProvider, Type type) { return string.Concat(value, '_', _suffix); } diff --git a/tests/Lykke.HttpClientGenerator.Tests/Lykke.HttpClientGenerator.Tests.csproj b/tests/Lykke.HttpClientGenerator.Tests/Lykke.HttpClientGenerator.Tests.csproj index 1e4f792..55b4f75 100644 --- a/tests/Lykke.HttpClientGenerator.Tests/Lykke.HttpClientGenerator.Tests.csproj +++ b/tests/Lykke.HttpClientGenerator.Tests/Lykke.HttpClientGenerator.Tests.csproj @@ -12,7 +12,7 @@ - +