feat(backend): add admin evaluation history, engine, simulation, bot API controllers and global exception middleware
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Diagnostics;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace FinlyticBackend.Middleware;
|
||||
|
||||
/// <summary>
|
||||
/// Global fallback exception handler for the Gateway (Rules.md §11). Converts any unhandled exception that
|
||||
/// escapes a controller action, hub method, or other endpoint into a standardized RFC 7807 Problem Details
|
||||
/// response instead of an ad-hoc anonymous error object or a leaked stack trace.
|
||||
/// Registered via <c>AddExceptionHandler<GlobalExceptionHandler>()</c> and activated by
|
||||
/// <c>app.UseExceptionHandler()</c> in <c>Program.cs</c>. This only intercepts exceptions thrown while a
|
||||
/// request is being handled; it has no effect on the fail-fast startup checks in <c>Program.cs</c>
|
||||
/// (missing/weak <c>JWT:SecretKey</c>, missing <c>ADMIN:DefaultPassword</c>), which throw before
|
||||
/// <c>builder.Build()</c> - i.e. before this middleware pipeline exists - and are intentionally left
|
||||
/// unhandled so the host refuses to start.
|
||||
/// </summary>
|
||||
public sealed class GlobalExceptionHandler : IExceptionHandler
|
||||
{
|
||||
private readonly ILogger<GlobalExceptionHandler> _logger;
|
||||
|
||||
public GlobalExceptionHandler(ILogger<GlobalExceptionHandler> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async ValueTask<bool> TryHandleAsync(HttpContext httpContext, Exception exception, CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.LogError(
|
||||
exception,
|
||||
"Unhandled exception while processing {Method} {Path}",
|
||||
httpContext.Request.Method,
|
||||
httpContext.Request.Path);
|
||||
|
||||
httpContext.Response.StatusCode = StatusCodes.Status500InternalServerError;
|
||||
|
||||
var problemDetailsService = httpContext.RequestServices.GetRequiredService<IProblemDetailsService>();
|
||||
return await problemDetailsService.TryWriteAsync(new ProblemDetailsContext
|
||||
{
|
||||
HttpContext = httpContext,
|
||||
Exception = exception,
|
||||
ProblemDetails = new ProblemDetails
|
||||
{
|
||||
Status = StatusCodes.Status500InternalServerError,
|
||||
Title = "An unexpected error occurred.",
|
||||
Detail = "The Gateway encountered an unexpected error while processing the request.",
|
||||
Type = "https://tools.ietf.org/html/rfc7231#section-6.6.1"
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user