From 9fcb7909cfa44f9c508c874cf3688fdc00bb4552 Mon Sep 17 00:00:00 2001 From: Leshchev Artem Date: Mon, 13 May 2024 22:13:27 +0200 Subject: [PATCH] Add platform API middlewares (#9) Co-authored-by: Artem Leshchev --- README.md | 31 +++++++++++++++- .../Bss.Platform.Api.Middlewares.csproj | 9 +++++ .../DependencyInjection.cs | 9 +++++ .../ErrorsMiddleware.cs | 35 +++++++++++++++++++ .../Interfaces/IStatusCodeResolver.cs | 8 +++++ src/Bss.Platform.sln | 7 ++++ src/Directory.Packages.props | 1 + src/__SolutionItems/CommonAssemblyInfo.cs | 6 ++-- 8 files changed, 102 insertions(+), 4 deletions(-) create mode 100644 src/Bss.Platform.Api.Middlewares/Bss.Platform.Api.Middlewares.csproj create mode 100644 src/Bss.Platform.Api.Middlewares/DependencyInjection.cs create mode 100644 src/Bss.Platform.Api.Middlewares/ErrorsMiddleware.cs create mode 100644 src/Bss.Platform.Api.Middlewares/Interfaces/IStatusCodeResolver.cs diff --git a/README.md b/README.md index ad95f5b..3890c03 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,16 @@ This repository offers a wide collection of .NET packages for use in microservices architecture. +# Sections + +- [RabbitMQ Consumer](#Consumer) +- [Logging](#Logging) +- [API Middlewares](#Middlewares) +- [API Documentation](#Documentation) +- [Kubernetes Insights](#Insights) +- [Kubernetes Health Checks](#Health-Checks) +- [NHibernate](#NHibernate) + ## RabbitMQ ### Consumer @@ -85,7 +95,26 @@ Finally, register sinks in appsettings.json file } } ``` -## API Documentation +## API + +### Middlewares +To use platform API middlewares, first install the [NuGet package](https://www.nuget.org/packages/Luxoft.Bss.Platform.Api.Middlewares): +```shell +dotnet add package Luxoft.Bss.Platform.Api.Middlewares +``` + +#### Errors +To log exceptions you need to use errors middleware. +```C# +app.UsePlatformErrorsMiddleware(); // This middleware should be the first +``` +> [!IMPORTANT] +> If you need to change response status code, then you should register status code resolver. +```C# +services.AddSingleton(); +``` + +### Documentation To use platform API documentation, first install the [NuGet package](https://www.nuget.org/packages/Luxoft.Bss.Platform.Api.Documentation): ```shell dotnet add package Luxoft.Bss.Platform.Api.Documentation diff --git a/src/Bss.Platform.Api.Middlewares/Bss.Platform.Api.Middlewares.csproj b/src/Bss.Platform.Api.Middlewares/Bss.Platform.Api.Middlewares.csproj new file mode 100644 index 0000000..575d388 --- /dev/null +++ b/src/Bss.Platform.Api.Middlewares/Bss.Platform.Api.Middlewares.csproj @@ -0,0 +1,9 @@ + + + Luxoft.Bss.Platform.Api.Middlewares + + + + + + diff --git a/src/Bss.Platform.Api.Middlewares/DependencyInjection.cs b/src/Bss.Platform.Api.Middlewares/DependencyInjection.cs new file mode 100644 index 0000000..bca53e8 --- /dev/null +++ b/src/Bss.Platform.Api.Middlewares/DependencyInjection.cs @@ -0,0 +1,9 @@ +using Microsoft.AspNetCore.Builder; + +namespace Bss.Platform.Api.Middlewares; + +public static class DependencyInjection +{ + public static IApplicationBuilder UsePlatformErrorsMiddleware(this IApplicationBuilder app) => + app.UseMiddleware(); +} diff --git a/src/Bss.Platform.Api.Middlewares/ErrorsMiddleware.cs b/src/Bss.Platform.Api.Middlewares/ErrorsMiddleware.cs new file mode 100644 index 0000000..d4ce105 --- /dev/null +++ b/src/Bss.Platform.Api.Middlewares/ErrorsMiddleware.cs @@ -0,0 +1,35 @@ +using System.Net; +using System.Net.Mime; +using System.Text.Json; + +using Bss.Platform.Api.Middlewares.Interfaces; + +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; + +namespace Bss.Platform.Api.Middlewares; + +public class ErrorsMiddleware(RequestDelegate next, ILogger logger, IStatusCodeResolver? statusCodeResolver) +{ + public async Task Invoke(HttpContext context) + { + try + { + await next(context); + } + catch (Exception e) + { + logger.LogError(e, "Request failed"); + + await this.HandleExceptionAsync(context, e); + } + } + + private Task HandleExceptionAsync(HttpContext context, Exception exception) + { + context.Response.ContentType = MediaTypeNames.Application.Json; + context.Response.StatusCode = (int)(statusCodeResolver?.Resolve(exception) ?? HttpStatusCode.InternalServerError); + + return context.Response.WriteAsync(JsonSerializer.Serialize(exception.GetBaseException().Message)); + } +} diff --git a/src/Bss.Platform.Api.Middlewares/Interfaces/IStatusCodeResolver.cs b/src/Bss.Platform.Api.Middlewares/Interfaces/IStatusCodeResolver.cs new file mode 100644 index 0000000..bcd4821 --- /dev/null +++ b/src/Bss.Platform.Api.Middlewares/Interfaces/IStatusCodeResolver.cs @@ -0,0 +1,8 @@ +using System.Net; + +namespace Bss.Platform.Api.Middlewares.Interfaces; + +public interface IStatusCodeResolver +{ + HttpStatusCode Resolve(Exception exception); +} diff --git a/src/Bss.Platform.sln b/src/Bss.Platform.sln index dac04f1..b5cf3c5 100644 --- a/src/Bss.Platform.sln +++ b/src/Bss.Platform.sln @@ -26,6 +26,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Kubernetes", "Kubernetes", EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bss.Platform.Kubernetes", "Bss.Platform.Kubernetes\Bss.Platform.Kubernetes.csproj", "{1BD00077-8005-42E9-AEFE-62A21E057858}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bss.Platform.Api.Middlewares", "Bss.Platform.Api.Middlewares\Bss.Platform.Api.Middlewares.csproj", "{285EBB7B-6B2A-453E-98F6-30AC38317A76}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -39,6 +41,7 @@ Global {2417B26C-C12D-4E63-8996-395DD78F81A1} = {D07584C3-F6D5-472C-8515-7D38F4C54F11} {0005DAE1-3F66-4A98-A11B-DEFDF2BD7EA3} = {8F22FE4E-8FD4-4309-8B47-C33AA6E52052} {1BD00077-8005-42E9-AEFE-62A21E057858} = {51F57F48-6CDC-43E2-90DA-B73C12EA2185} + {285EBB7B-6B2A-453E-98F6-30AC38317A76} = {8F22FE4E-8FD4-4309-8B47-C33AA6E52052} EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {860BFBD8-26EA-44F9-980E-21B828FC8F72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU @@ -69,5 +72,9 @@ Global {1BD00077-8005-42E9-AEFE-62A21E057858}.Debug|Any CPU.Build.0 = Debug|Any CPU {1BD00077-8005-42E9-AEFE-62A21E057858}.Release|Any CPU.ActiveCfg = Release|Any CPU {1BD00077-8005-42E9-AEFE-62A21E057858}.Release|Any CPU.Build.0 = Release|Any CPU + {285EBB7B-6B2A-453E-98F6-30AC38317A76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {285EBB7B-6B2A-453E-98F6-30AC38317A76}.Debug|Any CPU.Build.0 = Debug|Any CPU + {285EBB7B-6B2A-453E-98F6-30AC38317A76}.Release|Any CPU.ActiveCfg = Release|Any CPU + {285EBB7B-6B2A-453E-98F6-30AC38317A76}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props index 11d85cd..cd896b7 100644 --- a/src/Directory.Packages.props +++ b/src/Directory.Packages.props @@ -8,6 +8,7 @@ + diff --git a/src/__SolutionItems/CommonAssemblyInfo.cs b/src/__SolutionItems/CommonAssemblyInfo.cs index fcdb508..975f3bd 100644 --- a/src/__SolutionItems/CommonAssemblyInfo.cs +++ b/src/__SolutionItems/CommonAssemblyInfo.cs @@ -4,9 +4,9 @@ [assembly: AssemblyCompany("Luxoft")] [assembly: AssemblyCopyright("Copyright © Luxoft 2024")] -[assembly: AssemblyVersion("1.2.0.0")] -[assembly: AssemblyFileVersion("1.2.0.0")] -[assembly: AssemblyInformationalVersion("1.2.0.0")] +[assembly: AssemblyVersion("1.3.0.0")] +[assembly: AssemblyFileVersion("1.3.0.0")] +[assembly: AssemblyInformationalVersion("1.3.0.0")] #if DEBUG [assembly: AssemblyConfiguration("Debug")]