50 lines
1.8 KiB
C#
50 lines
1.8 KiB
C#
|
|
using System.Net;
|
||
|
|
using System.Text.Json;
|
||
|
|
using FlatRender.IdentitySvc.Models.Responses;
|
||
|
|
|
||
|
|
namespace FlatRender.IdentitySvc.Middleware;
|
||
|
|
|
||
|
|
public class ExceptionMiddleware(RequestDelegate next, ILogger<ExceptionMiddleware> logger)
|
||
|
|
{
|
||
|
|
private static readonly JsonSerializerOptions JsonOptions = new() { PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower };
|
||
|
|
|
||
|
|
public async Task InvokeAsync(HttpContext context)
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
await next(context);
|
||
|
|
}
|
||
|
|
catch (Exception ex)
|
||
|
|
{
|
||
|
|
await HandleExceptionAsync(context, ex);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private async Task HandleExceptionAsync(HttpContext context, Exception ex)
|
||
|
|
{
|
||
|
|
var traceId = context.TraceIdentifier;
|
||
|
|
|
||
|
|
var (status, code, message) = ex switch
|
||
|
|
{
|
||
|
|
KeyNotFoundException => (HttpStatusCode.NotFound, "NOT_FOUND", ex.Message),
|
||
|
|
UnauthorizedAccessException => (HttpStatusCode.Unauthorized, "UNAUTHORIZED", ex.Message),
|
||
|
|
InvalidOperationException => (HttpStatusCode.BadRequest, "INVALID_OPERATION", ex.Message),
|
||
|
|
ArgumentException => (HttpStatusCode.BadRequest, "INVALID_ARGUMENT", ex.Message),
|
||
|
|
NotImplementedException => (HttpStatusCode.NotImplemented, "NOT_IMPLEMENTED", ex.Message),
|
||
|
|
_ => (HttpStatusCode.InternalServerError, "INTERNAL_ERROR", "An unexpected error occurred"),
|
||
|
|
};
|
||
|
|
|
||
|
|
if (status == HttpStatusCode.InternalServerError)
|
||
|
|
logger.LogError(ex, "Unhandled exception {TraceId}", traceId);
|
||
|
|
|
||
|
|
context.Response.StatusCode = (int)status;
|
||
|
|
context.Response.ContentType = "application/json";
|
||
|
|
|
||
|
|
var body = JsonSerializer.Serialize(
|
||
|
|
new { error = new ApiError(code, message, null, traceId) },
|
||
|
|
JsonOptions);
|
||
|
|
|
||
|
|
await context.Response.WriteAsync(body);
|
||
|
|
}
|
||
|
|
}
|