Foxchat.NET/Foxchat.Core/Middleware/ErrorHandlerMiddleware.cs

86 lines
No EOL
3.2 KiB
C#

using System.Net;
using Foxchat.Core.Models.Http;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using HttpApiError = Foxchat.Core.Models.Http.ApiError;
namespace Foxchat.Core.Middleware;
public class ErrorHandlerMiddleware(ILogger baseLogger) : IMiddleware
{
public async Task InvokeAsync(HttpContext ctx, RequestDelegate next)
{
try
{
await next(ctx);
}
catch (Exception e)
{
var type = e.TargetSite?.DeclaringType ?? typeof(ErrorHandlerMiddleware);
var typeName = e.TargetSite?.DeclaringType?.FullName ?? "<unknown>";
var logger = baseLogger.ForContext(type);
if (ctx.Response.HasStarted)
{
logger.Error(e, "Error in {ClassName} ({Path}) after response started being sent", typeName,
ctx.Request.Path);
}
if (e is ApiError ae)
{
ctx.Response.StatusCode = (int)ae.StatusCode;
ctx.Response.Headers.RequestId = ctx.TraceIdentifier;
ctx.Response.ContentType = "application/json; charset=utf-8";
if (ae is ApiError.OutgoingFederationError ofe)
{
await ctx.Response.WriteAsync(JsonConvert.SerializeObject(new HttpApiError
{
Status = (int)ofe.StatusCode,
Code = ErrorCode.OutgoingFederationError,
Message = ofe.Message,
OriginalError = ofe.InnerError
}));
return;
}
else if (ae is ApiError.Forbidden fe)
{
await ctx.Response.WriteAsync(JsonConvert.SerializeObject(new HttpApiError
{
Status = (int)fe.StatusCode,
Code = ErrorCode.Forbidden,
Message = fe.Message,
Scopes = fe.Scopes.Length > 0 ? fe.Scopes : null
}));
return;
}
await ctx.Response.WriteAsync(JsonConvert.SerializeObject(new HttpApiError
{
Status = (int)ae.StatusCode,
Code = ErrorCode.GenericApiError,
Message = ae.Message,
}));
return;
}
if (e is FoxchatError fce)
{
logger.Error(fce.Inner ?? fce, "Exception in {ClassName} ({Path})", typeName, ctx.Request.Path);
}
else
{
logger.Error(e, "Exception in {ClassName} ({Path})", typeName, ctx.Request.Path);
}
ctx.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
ctx.Response.Headers.RequestId = ctx.TraceIdentifier;
ctx.Response.ContentType = "application/json; charset=utf-8";
await ctx.Response.WriteAsync(JsonConvert.SerializeObject(new HttpApiError
{
Status = (int)HttpStatusCode.InternalServerError,
Code = ErrorCode.InternalServerError,
Message = "Internal server error",
}));
}
}
}