[backend/asp] Improve validation error handling

This commit is contained in:
Laura Hausmann 2024-07-10 02:42:42 +02:00
parent 09cda1a89e
commit 769a94d83c
No known key found for this signature in database
GPG key ID: D044E84C5BE01605
3 changed files with 24 additions and 25 deletions

View file

@ -9,7 +9,6 @@ using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.Extensions.ObjectPool;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using JsonSerializer = System.Text.Json.JsonSerializer;
namespace Iceshrimp.Backend.Core.Extensions;
@ -82,9 +81,8 @@ public static class MvcBuilderExtensions
var message = details.Title ?? "One or more validation errors occurred.";
if (details.Detail != null)
message += $" - {details.Detail}";
var errors = JsonSerializer.Serialize(details.Errors);
throw new GracefulException(status, status.ToString(), message, errors);
throw new ValidationException(status, status.ToString(), message, details.Errors);
};
});

View file

@ -76,37 +76,25 @@ public class ErrorHandlerMiddleware(
ctx.Response.StatusCode = (int)ce.StatusCode;
ctx.Response.Headers.RequestId = ctx.TraceIdentifier;
// @formatter:off
if (isMastodon)
await ctx.Response.WriteAsJsonAsync(new MastodonErrorResponse
{
Error = verbosity >= ExceptionVerbosity.Basic
? ce.Message
: ce.StatusCode.ToString(),
Description = verbosity >= ExceptionVerbosity.Basic
? ce.Details
: null
Error = verbosity >= ExceptionVerbosity.Basic ? ce.Message : ce.StatusCode.ToString(),
Description = verbosity >= ExceptionVerbosity.Basic ? ce.Details : null
});
else
await ctx.Response.WriteAsJsonAsync(new ErrorResponse
{
StatusCode = ctx.Response.StatusCode,
Error =
verbosity >= ExceptionVerbosity.Basic
? ce.Error
: ce.StatusCode.ToString(),
Message =
verbosity >= ExceptionVerbosity.Basic
? ce.Message
: null,
Details =
verbosity == ExceptionVerbosity.Full
? ce.Details
: null,
Source = verbosity == ExceptionVerbosity.Full
? type
: null,
RequestId = ctx.TraceIdentifier
Error = verbosity >= ExceptionVerbosity.Basic ? ce.Error : ce.StatusCode.ToString(),
Message = verbosity >= ExceptionVerbosity.Basic ? ce.Message : null,
Details = verbosity == ExceptionVerbosity.Full ? ce.Details : null,
Errors = verbosity == ExceptionVerbosity.Full ? (ce as ValidationException)?.Errors : null,
Source = verbosity == ExceptionVerbosity.Full ? type : null,
RequestId = ctx.TraceIdentifier
});
// @formatter:on
var level = ce.SuppressLog ? LogLevel.Trace : LogLevel.Debug;
@ -225,6 +213,16 @@ public class InstanceBlockedException(string uri, string? host = null)
public string Uri => uri;
}
public class ValidationException(
HttpStatusCode statusCode,
string error,
string message,
IDictionary<string, string[]> errors
) : GracefulException(statusCode, error, message)
{
public IDictionary<string, string[]> Errors => errors;
}
public enum ExceptionVerbosity
{
[SuppressMessage("ReSharper", "UnusedMember.Global")]

View file

@ -14,6 +14,9 @@ public class ErrorResponse
[JI(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Details { get; set; }
[JI(Condition = JsonIgnoreCondition.WhenWritingNull)]
public IDictionary<string, string[]>? Errors { get; set; }
[JI(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Source { get; set; }