using System; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using SimApi.Communications; using Microsoft.Extensions.Logging; using SimApi.Configurations; using SimApi.Exceptions; using SimApi.Helpers; namespace SimApi.Middlewares; /// /// 异常处理中间件 /// public class SimApiExceptionMiddleware( RequestDelegate next, ILogger log, SimApiOptions simApiOptions) { public async Task InvokeAsync(HttpContext context) { if (context.Request.Headers.TryGetValue("Query-Id", out var header)) { context.Response.Headers["Query-Id"] = header; } try { await next(context); if (!context.Response.HasStarted) { SimApiError.ErrorWhenFalse( simApiOptions.SimApiExceptionOptions.SkipStatusCodes.Contains(context.Response.StatusCode), context.Response.StatusCode); } } catch (Exception ex) { // 解包异步异常 ex = UnwrapAggregateException(ex); SimApiBaseResponse response; if (ex is SimApiException simEx) { response = string.IsNullOrEmpty(simEx.Message) ? new SimApiBaseResponse(simEx.Code) : new SimApiBaseResponse(simEx.Code, simEx.Message); if (context.Response.StatusCode == 404) { response.Message = "接口不存在"; } } else { log.LogError(ex, ex.Message); response = new SimApiBaseResponse(500); } await ErrorResponseAsync(context, response); } } private static Exception UnwrapAggregateException(Exception ex) { while (ex is AggregateException aggEx && aggEx.InnerException != null) { ex = aggEx.InnerException; } return ex; } /// /// 异步输出错误响应(修复异步异常捕获核心) /// private static async Task ErrorResponseAsync(HttpContext context, SimApiBaseResponse response) { // 响应已开始则直接返回,不修改 if (context.Response.HasStarted) return; context.Response.StatusCode = 200; context.Response.ContentType = "application/json"; context.Response.ContentLength = null; // 清除可能已设置的 Content-Length await context.Response.WriteAsync(response.ToString()); } }