// Copyright (C) 2021-present sam (starshines.gay) // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published // by the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . using System.Net; using System.Text.Json.Serialization; namespace Catalogger.Backend.Api.Middleware; public class ErrorMiddleware(ILogger baseLogger) : IMiddleware { public async Task InvokeAsync(HttpContext context, RequestDelegate next) { try { await next(context); } catch (ApiError ae) { context.Response.StatusCode = (int)ae.StatusCode; await context.Response.WriteAsJsonAsync(ae.ToJson()); } catch (Exception e) { var type = e.TargetSite?.DeclaringType ?? typeof(ErrorMiddleware); var typeName = e.TargetSite?.DeclaringType?.FullName ?? ""; var logger = baseLogger.ForContext(type); logger.Error(e, "Error in {ClassName} ({Path})", typeName, context.Request.Path); context.Response.StatusCode = StatusCodes.Status500InternalServerError; await context.Response.WriteAsJsonAsync( new ApiError( HttpStatusCode.InternalServerError, ErrorCode.InternalServerError, "Internal server error" ).ToJson() ); } } } public class ApiError(HttpStatusCode statusCode, ErrorCode errorCode, string message) : Exception(message) { public HttpStatusCode StatusCode { get; init; } = statusCode; public ErrorCode ErrorCode { get; init; } = errorCode; private record Json(ErrorCode ErrorCode, string Message); public object ToJson() => new Json(ErrorCode, Message); } [JsonConverter(typeof(JsonStringEnumConverter))] public enum ErrorCode { InternalServerError, BadRequest, AuthRequired, UnknownGuild, }