v9.10.2019.0101  全面巩固批量Insert/Update/Upsert,支持数据备份、恢复和同步,支持实体列表保存到文件以及加载
大石头 authored at 2019-01-01 13:38:33
2.00 KiB
X
using System.Net;
using NewLife.Data;
using NewLife.Serialization;

namespace NewLife.Http;

/// <summary>全局错误处理中间件</summary>
/// <remarks>
/// 捕获处理器中抛出的异常并转换为结构化 HTTP 错误响应。
/// 
/// <code>
/// server.Use(new ErrorHandlerMiddleware
/// {
///     IncludeDetails = true  // 开发模式返回详细异常信息
/// });
/// </code>
/// </remarks>
public class ErrorHandlerMiddleware
{
    #region 属性
    /// <summary>是否在响应中包含详细异常信息(堆栈跟踪等)。生产环境应设为 false</summary>
    public Boolean IncludeDetails { get; set; }
    #endregion

    /// <summary>中间件入口</summary>
    /// <param name="context">Http上下文</param>
    /// <param name="next">下一个中间件</param>
    /// <returns></returns>
    public async Task Invoke(IHttpContext context, Func<Task> next)
    {
        try
        {
            await next().ConfigureAwait(false);
        }
        catch (HttpException hex)
        {
            SetErrorResponse(context, hex.StatusCode, hex.Message, IncludeDetails ? hex : null);
        }
        catch (Exception ex)
        {
            SetErrorResponse(context, HttpStatusCode.InternalServerError, ex.Message, IncludeDetails ? ex : null);
        }
    }

    private static void SetErrorResponse(IHttpContext context, HttpStatusCode code, String message, Exception? detail)
    {
        var res = context.Response;
        res.StatusCode = code;

        if (detail != null)
        {
            // 开发模式返回结构化错误
            var error = new
            {
                error = new
                {
                    code = (Int32)code,
                    message,
                    detail = detail.ToString()
                }
            };
            res.ContentType = "application/json; charset=utf-8";
            res.Body = (ArrayPacket)error.ToJson().GetBytes();
        }
        else
        {
            res.StatusDescription = message;
        }
    }
}