feat(apiv2): basic error handling
This commit is contained in:
parent
9bafc732ab
commit
9d47bfe0d8
51
PluralKit.API/Errors.cs
Normal file
51
PluralKit.API/Errors.cs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
namespace PluralKit.API
|
||||||
|
{
|
||||||
|
public class PKError: Exception
|
||||||
|
{
|
||||||
|
public int ResponseCode { get; init; }
|
||||||
|
public int JsonCode { get; init; }
|
||||||
|
public PKError(int code, int json_code, string message) : base(message)
|
||||||
|
{
|
||||||
|
ResponseCode = code;
|
||||||
|
JsonCode = json_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JObject ToJson()
|
||||||
|
{
|
||||||
|
var j = new JObject();
|
||||||
|
j.Add("message", this.Message);
|
||||||
|
j.Add("code", this.JsonCode);
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ModelParseError: PKError
|
||||||
|
{
|
||||||
|
public ModelParseError() : base(400, 0, "Error parsing JSON model")
|
||||||
|
{
|
||||||
|
// todo
|
||||||
|
}
|
||||||
|
|
||||||
|
public new JObject ToJson()
|
||||||
|
{
|
||||||
|
var j = base.ToJson();
|
||||||
|
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class APIErrors
|
||||||
|
{
|
||||||
|
public static PKError GenericBadRequest = new(400, 0, "400: Bad Request");
|
||||||
|
public static PKError SystemNotFound = new(404, 20001, "System not found.");
|
||||||
|
public static PKError MemberNotFound = new(404, 20002, "Member not found.");
|
||||||
|
public static PKError GroupNotFound = new(404, 20003, "Group not found.");
|
||||||
|
public static PKError UnauthorizedMemberList = new(403, 30001, "Unauthorized to view member list");
|
||||||
|
public static PKError UnauthorizedGroupList = new(403, 30002, "Unauthorized to view group list");
|
||||||
|
public static PKError Unimplemented = new(501, 50001, "Unimplemented");
|
||||||
|
}
|
||||||
|
}
|
@ -7,7 +7,9 @@ using Autofac;
|
|||||||
using Microsoft.AspNetCore.Authentication;
|
using Microsoft.AspNetCore.Authentication;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.Diagnostics;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Mvc.Versioning;
|
using Microsoft.AspNetCore.Mvc.Versioning;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
@ -15,6 +17,10 @@ using Microsoft.Extensions.DependencyInjection;
|
|||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.OpenApi.Models;
|
using Microsoft.OpenApi.Models;
|
||||||
|
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
using Serilog;
|
||||||
|
|
||||||
using PluralKit.Core;
|
using PluralKit.Core;
|
||||||
|
|
||||||
namespace PluralKit.API
|
namespace PluralKit.API
|
||||||
@ -91,7 +97,7 @@ namespace PluralKit.API
|
|||||||
builder.RegisterInstance(InitUtils.BuildConfiguration(Environment.GetCommandLineArgs()).Build())
|
builder.RegisterInstance(InitUtils.BuildConfiguration(Environment.GetCommandLineArgs()).Build())
|
||||||
.As<IConfiguration>();
|
.As<IConfiguration>();
|
||||||
builder.RegisterModule(new ConfigModule<ApiConfig>("API"));
|
builder.RegisterModule(new ConfigModule<ApiConfig>("API"));
|
||||||
builder.RegisterModule(new LoggingModule("api"));
|
builder.RegisterModule(new LoggingModule("api", cfg: new LoggerConfiguration().Filter.ByExcluding(exc => exc.Exception is PKError)));
|
||||||
builder.RegisterModule(new MetricsModule("API"));
|
builder.RegisterModule(new MetricsModule("API"));
|
||||||
builder.RegisterModule<DataStoreModule>();
|
builder.RegisterModule<DataStoreModule>();
|
||||||
builder.RegisterModule<APIModule>();
|
builder.RegisterModule<APIModule>();
|
||||||
@ -124,6 +130,23 @@ namespace PluralKit.API
|
|||||||
return next();
|
return next();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.UseExceptionHandler(handler => handler.Run(async ctx =>
|
||||||
|
{
|
||||||
|
var exc = ctx.Features.Get<IExceptionHandlerPathFeature>();
|
||||||
|
if (exc.Error is not PKError)
|
||||||
|
{
|
||||||
|
ctx.Response.StatusCode = 500;
|
||||||
|
await ctx.Response.WriteAsync("{\"message\":\"500: Internal Server Error\",\"code\":0}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var err = (PKError)exc.Error;
|
||||||
|
ctx.Response.StatusCode = err.ResponseCode;
|
||||||
|
|
||||||
|
var json = JsonConvert.SerializeObject(err.ToJson());
|
||||||
|
await ctx.Response.WriteAsync(json);
|
||||||
|
}));
|
||||||
|
|
||||||
app.UseMiddleware<AuthorizationTokenHandlerMiddleware>();
|
app.UseMiddleware<AuthorizationTokenHandlerMiddleware>();
|
||||||
|
|
||||||
//app.UseHttpsRedirection();
|
//app.UseHttpsRedirection();
|
||||||
|
@ -17,11 +17,13 @@ namespace PluralKit.Core
|
|||||||
{
|
{
|
||||||
private readonly string _component;
|
private readonly string _component;
|
||||||
private readonly Action<LoggerConfiguration> _fn;
|
private readonly Action<LoggerConfiguration> _fn;
|
||||||
|
private LoggerConfiguration _cfg { get; init; }
|
||||||
|
|
||||||
public LoggingModule(string component, Action<LoggerConfiguration> fn = null)
|
public LoggingModule(string component, Action<LoggerConfiguration> fn = null, LoggerConfiguration cfg = null)
|
||||||
{
|
{
|
||||||
_component = component;
|
_component = component;
|
||||||
_fn = fn ?? (_ => { });
|
_fn = fn ?? (_ => { });
|
||||||
|
_cfg = cfg ?? new LoggerConfiguration();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Load(ContainerBuilder builder)
|
protected override void Load(ContainerBuilder builder)
|
||||||
@ -44,7 +46,7 @@ namespace PluralKit.Core
|
|||||||
var consoleTemplate = "[{Timestamp:HH:mm:ss.fff}] {Level:u3} {Message:lj}{NewLine}{Exception}";
|
var consoleTemplate = "[{Timestamp:HH:mm:ss.fff}] {Level:u3} {Message:lj}{NewLine}{Exception}";
|
||||||
var outputTemplate = "[{Timestamp:yyyy-MM-dd HH:mm:ss.ffffff}] {Level:u3} {Message:lj}{NewLine}{Exception}";
|
var outputTemplate = "[{Timestamp:yyyy-MM-dd HH:mm:ss.ffffff}] {Level:u3} {Message:lj}{NewLine}{Exception}";
|
||||||
|
|
||||||
var logCfg = new LoggerConfiguration()
|
var logCfg = _cfg
|
||||||
.Enrich.FromLogContext()
|
.Enrich.FromLogContext()
|
||||||
.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb)
|
.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb)
|
||||||
.Enrich.WithProperty("Component", _component)
|
.Enrich.WithProperty("Component", _component)
|
||||||
@ -53,6 +55,9 @@ namespace PluralKit.Core
|
|||||||
// Don't want App.Metrics/D#+ spam
|
// Don't want App.Metrics/D#+ spam
|
||||||
.MinimumLevel.Override("App.Metrics", LogEventLevel.Information)
|
.MinimumLevel.Override("App.Metrics", LogEventLevel.Information)
|
||||||
|
|
||||||
|
// nor ASP.NET spam
|
||||||
|
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
|
||||||
|
|
||||||
// Actual formatting for these is handled in ScalarFormatting
|
// Actual formatting for these is handled in ScalarFormatting
|
||||||
.Destructure.AsScalar<SystemId>()
|
.Destructure.AsScalar<SystemId>()
|
||||||
.Destructure.AsScalar<MemberId>()
|
.Destructure.AsScalar<MemberId>()
|
||||||
|
Loading…
Reference in New Issue
Block a user