Iceshrimp.NET/Iceshrimp.Backend/Core/Middleware/ErrorHandlerMiddleware.cs
2024-01-24 19:14:01 +01:00

59 lines
No EOL
2.2 KiB
C#

using System.Net;
using Iceshrimp.Backend.Controllers.Schemas;
namespace Iceshrimp.Backend.Core.Middleware;
public class ErrorHandlerMiddleware(ILoggerFactory loggerFactory) : IMiddleware {
public async Task InvokeAsync(HttpContext ctx, RequestDelegate next) {
try {
await next(ctx);
}
catch (Exception e) {
ctx.Response.ContentType = "application/json";
// Get the name of the class & function where the exception originated, falling back to this one
var type = e.TargetSite?.DeclaringType?.FullName ?? typeof(ErrorHandlerMiddleware).FullName!;
if (type.Contains('>'))
type = type[..(type.IndexOf('>') + 1)];
var logger = loggerFactory.CreateLogger(type);
if (e is GracefulException ce) {
ctx.Response.StatusCode = (int)ce.StatusCode;
await ctx.Response.WriteAsJsonAsync(new ErrorResponse {
StatusCode = ctx.Response.StatusCode,
Error = ce.Error,
Message = ce.Message,
RequestId = ctx.TraceIdentifier
});
logger.LogDebug("Request {id} was rejected with {statusCode} {error} due to: {message}",
ctx.TraceIdentifier, (int)ce.StatusCode, ce.Error, ce.Message);
}
else {
ctx.Response.StatusCode = 500;
await ctx.Response.WriteAsJsonAsync(new ErrorResponse {
StatusCode = 500,
Error = "Internal Server Error",
Message = e.Message,
RequestId = ctx.TraceIdentifier
});
//TODO: use the overload that takes an exception instead of printing it ourselves
logger.LogError("Request {id} encountered an unexpected error: {exception}", ctx.TraceIdentifier,
e.ToString());
}
}
}
}
//TODO: Allow specifying differing messages for api response and server logs
//TODO: Make this configurable
public class GracefulException(HttpStatusCode statusCode, string error, string message) : Exception(message) {
public readonly string Error = error;
public readonly HttpStatusCode StatusCode = statusCode;
public GracefulException(HttpStatusCode statusCode, string message) :
this(statusCode, statusCode.ToString(), message) { }
public GracefulException(string message) :
this(HttpStatusCode.InternalServerError, HttpStatusCode.InternalServerError.ToString(), message) { }
}