diff --git a/src/NuGet.Next/Apis/ApiExtensions.cs b/src/NuGet.Next/Apis/ApiExtensions.cs index 8c52e08..9b1ce64 100644 --- a/src/NuGet.Next/Apis/ApiExtensions.cs +++ b/src/NuGet.Next/Apis/ApiExtensions.cs @@ -1,5 +1,6 @@ using Microsoft.AspNetCore.Mvc; using NuGet.Next.Core; +using NuGet.Next.Filter; using NuGet.Next.Options; using NuGet.Next.Protocol.Models; @@ -11,7 +12,8 @@ public static IEndpointRouteBuilder MapApis(this IEndpointRouteBuilder app) { var options = app.ServiceProvider.GetRequiredService(); - var group = app.MapGroup(options.PathBase ?? "/"); + var group = app.MapGroup(options.PathBase ?? "/") + .AddEndpointFilter(); group.Map("/v3/package/{id}/index.json", @@ -194,14 +196,14 @@ await apis.DeleteAsync(id)) async ([FromServices] UserKeyApis apis, string id) => await apis.EnableAsync(id)) .WithOpenApi(); - + var panel = group.MapGroup("api/v3/panel"); panel.MapGet(string.Empty, async ([FromServices] PanelApi apis) => await apis.GetAsync()) .WithOpenApi(); - + return app; } } \ No newline at end of file diff --git a/src/NuGet.Next/Filter/ExceptionFilter.cs b/src/NuGet.Next/Filter/ExceptionFilter.cs new file mode 100644 index 0000000..86b7311 --- /dev/null +++ b/src/NuGet.Next/Filter/ExceptionFilter.cs @@ -0,0 +1,74 @@ +using NuGet.Next.Core.Exceptions; +using NuGet.Next.Protocol.Models; + +namespace NuGet.Next.Filter; + +public class ExceptionFilter(ILogger logger) : IEndpointFilter +{ + public async ValueTask InvokeAsync(EndpointFilterInvocationContext context, EndpointFilterDelegate next) + { + try + { + return await next(context); + } + catch (NotFoundException notFoundException) + { + context.HttpContext.Response.StatusCode = 404; + context.HttpContext.Response.ContentType = "application/json"; + + logger.LogWarning("Resource not found: {Path}", context.HttpContext.Request.Path); + return new OkResponse(false, notFoundException.Message); + } + catch (UnauthorizedAccessException) + { + context.HttpContext.Response.StatusCode = 401; + context.HttpContext.Response.ContentType = "application/json"; + + var response = new OkResponse(false, "未授权的访问"); + + logger.LogWarning("Unauthorized access to {Path}", context.HttpContext.Request.Path); + + return response; + } + catch (Exception ex) + { + switch (ex) + { + case InvalidOperationException or BadRequestException: + { + context.HttpContext.Response.StatusCode = 200; + context.HttpContext.Response.ContentType = "application/json"; + + var response = new OkResponse(false, ex.Message); + + logger.LogWarning("Invalid operation: {Message}", ex.Message); + + return response; + } + case ForbiddenException: + { + context.HttpContext.Response.StatusCode = 403; + context.HttpContext.Response.ContentType = "application/json"; + + var response = new OkResponse(false, ex.Message); + + + logger.LogWarning("Forbidden access to {Path}", context.HttpContext.Request.Path); + + return response; + } + default: + { + context.HttpContext.Response.StatusCode = 500; + context.HttpContext.Response.ContentType = "application/json"; + + var response = new OkResponse(false, "服务器内部错误"); + + logger.LogError(ex, "An error occurred while processing {Path}", context.HttpContext.Request.Path); + + return response; + } + } + } + } +} \ No newline at end of file diff --git a/src/NuGet.Next/Middlewares/ExceptionMiddleware.cs b/src/NuGet.Next/Middlewares/ExceptionMiddleware.cs deleted file mode 100644 index 1c0d127..0000000 --- a/src/NuGet.Next/Middlewares/ExceptionMiddleware.cs +++ /dev/null @@ -1,86 +0,0 @@ -using Gnarly.Data; -using NuGet.Next.Core.Exceptions; -using NuGet.Next.Protocol.Models; - -namespace NuGet.Next.Middlewares; - -public class ExceptionMiddleware(ILogger logger) : IMiddleware, ISingletonDependency -{ - public async Task InvokeAsync(HttpContext context, RequestDelegate next) - { - try - { - if (context.Request.Path == "/") - { - context.Request.Path = "/index.html"; - } - - await next(context); - - if (context.Response.StatusCode == 404) - { - context.Request.Path = "/index.html"; - - await next(context); - } - } - catch (NotFoundException notFoundException) - { - context.Response.StatusCode = 404; - context.Response.ContentType = "application/json"; - - var response = new OkResponse(false, notFoundException.Message); - - await context.Response.WriteAsJsonAsync(response); - - logger.LogWarning("Resource not found: {Path}", context.Request.Path); - } - catch (UnauthorizedAccessException) - { - context.Response.StatusCode = 401; - context.Response.ContentType = "application/json"; - - var response = new OkResponse(false, "未授权的访问"); - - await context.Response.WriteAsJsonAsync(response); - - logger.LogWarning("Unauthorized access to {Path}", context.Request.Path); - } - catch (Exception ex) - { - if (ex is InvalidOperationException or BadRequestException) - { - context.Response.StatusCode = 200; - context.Response.ContentType = "application/json"; - - var response = new OkResponse(false, ex.Message); - - await context.Response.WriteAsJsonAsync(response); - - logger.LogWarning("Invalid operation: {Message}", ex.Message); - } - else if (ex is ForbiddenException) - { - context.Response.StatusCode = 403; - context.Response.ContentType = "application/json"; - - var response = new OkResponse(false, ex.Message); - - await context.Response.WriteAsJsonAsync(response); - - logger.LogWarning("Forbidden access to {Path}", context.Request.Path); - } - else - { - context.Response.StatusCode = 500; - context.Response.ContentType = "application/json"; - - var response = new OkResponse(false, "服务器内部错误"); - - await context.Response.WriteAsJsonAsync(response); - - logger.LogError(ex, "An error occurred while processing {Path}", context.Request.Path); - } - } - } -} \ No newline at end of file diff --git a/src/NuGet.Next/Program.cs b/src/NuGet.Next/Program.cs index 19f11d7..4d2f2da 100644 --- a/src/NuGet.Next/Program.cs +++ b/src/NuGet.Next/Program.cs @@ -4,7 +4,6 @@ using NuGet.Next; using NuGet.Next.Converters; using NuGet.Next.Extensions; -using NuGet.Next.Middlewares; using NuGet.Next.Service; Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory); @@ -57,8 +56,6 @@ app.Configure(builder.Environment, builder.Configuration); -app.UseMiddleware(); - app.UseResponseCompression(); app.UseStaticFiles();