74 lines
2.7 KiB
C#
74 lines
2.7 KiB
C#
|
|
using System.Text.Json;
|
||
|
|
using public_valetax.Exceptions;
|
||
|
|
using public_valetax.Repositories;
|
||
|
|
|
||
|
|
namespace public_valetax.Middleware
|
||
|
|
{
|
||
|
|
public class ExceptionHandlingMiddleware(RequestDelegate _next, ILogger<ExceptionHandlingMiddleware> _logger)
|
||
|
|
{
|
||
|
|
public async Task InvokeAsync(HttpContext context, IJournalRepository journalRepository)
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
if (context.Request.ContentLength > 0)
|
||
|
|
{
|
||
|
|
context.Request.EnableBuffering();
|
||
|
|
}
|
||
|
|
await _next(context);
|
||
|
|
}
|
||
|
|
catch (Exception ex)
|
||
|
|
{
|
||
|
|
_logger.LogError(ex, "An unhandled exception occurred");
|
||
|
|
|
||
|
|
// Generate event ID
|
||
|
|
var eventId = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
||
|
|
|
||
|
|
// Capture request details
|
||
|
|
var queryParameters = context.Request.QueryString.ToString();
|
||
|
|
string? bodyParameters = null;
|
||
|
|
|
||
|
|
// Try to capture body parameters (be careful not to consume the stream multiple times)
|
||
|
|
if (context.Request.ContentLength > 0)
|
||
|
|
{
|
||
|
|
context.Request.Body.Position = 0; // Reset for next middleware
|
||
|
|
using var reader = new StreamReader(context.Request.Body, leaveOpen: true);
|
||
|
|
bodyParameters = await reader.ReadToEndAsync();
|
||
|
|
context.Request.Body.Position = 0; // Reset for next middleware
|
||
|
|
}
|
||
|
|
|
||
|
|
// Log to journal
|
||
|
|
await journalRepository.CreateJournalEntryAsync(
|
||
|
|
eventId,
|
||
|
|
ex.GetType().Name,
|
||
|
|
ex.Message,
|
||
|
|
queryParameters,
|
||
|
|
bodyParameters,
|
||
|
|
ex.StackTrace);
|
||
|
|
|
||
|
|
// Handle specific exception types
|
||
|
|
await HandleExceptionAsync(context, ex, eventId);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private static async Task HandleExceptionAsync(HttpContext context, Exception exception, long eventId)
|
||
|
|
{
|
||
|
|
var response = new
|
||
|
|
{
|
||
|
|
type = exception is SecureException ? "Secure" : "Exception",
|
||
|
|
id = eventId.ToString(),
|
||
|
|
data = new
|
||
|
|
{
|
||
|
|
message = exception is SecureException
|
||
|
|
? exception.Message
|
||
|
|
: $"Internal server error ID = {eventId}"
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
context.Response.ContentType = "application/json";
|
||
|
|
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
|
||
|
|
|
||
|
|
var jsonResponse = JsonSerializer.Serialize(response);
|
||
|
|
await context.Response.WriteAsync(jsonResponse);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|