diff options
Diffstat (limited to 'ExceptionMiddleware.cs')
| -rw-r--r-- | ExceptionMiddleware.cs | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/ExceptionMiddleware.cs b/ExceptionMiddleware.cs new file mode 100644 index 0000000..29d0e10 --- /dev/null +++ b/ExceptionMiddleware.cs @@ -0,0 +1,64 @@ +using HyperBooru.ApiModels; +using System.Reflection; +using System.Text.Json; +using System.Text.Json.Serialization; +using System.Text.Json.Serialization.Metadata; + +namespace HyperBooru; + +// Middleware class to intercept API controller exceptions and +// return said exceptions to API clients as serialized JSON objects +public sealed class ExceptionMiddleware { + private RequestDelegate next; + + public ExceptionMiddleware(RequestDelegate next) => + this.next = next; + + public async Task Invoke(HttpContext context) { + try { + await next(context); + } catch(HBException e) { + context.Response.ContentType = "application/json"; + context.Response.StatusCode = + e.GetType().GetCustomAttribute<ExceptionStatusCodeAttribute>()?.StatusCode ?? + StatusCodes.Status500InternalServerError; + + await context.Response.WriteAsJsonAsync(e); + + var x = 1; + } catch(Exception) { + context.Response.StatusCode = StatusCodes.Status500InternalServerError; + context.Response.ContentType = "application/json"; + + context.Response.Clear(); + + await context.Response.WriteAsync(string.Empty); + } + } +} + +// This class is needed as the JSON serializer often fails to serialize +// members of the native 'Exception' class +public sealed class ExceptionJsonResolver : DefaultJsonTypeInfoResolver { + public override JsonTypeInfo GetTypeInfo(Type type, JsonSerializerOptions options) { + var info = base.GetTypeInfo(type, options); + + if(!typeof(Exception).IsAssignableFrom(type)) + return info; + + string[] excludedProps = [ + "data", + "hResult", + "helpLink", + "innerException", + "source", + "stackTrace", + "targetSite" + ]; + + foreach(var p in info.Properties.Where(p => excludedProps.Contains(p.Name))) + p.ShouldSerialize = (_, _) => false; + + return info; + } +} |
