Skip to content

Commit 7bd8705

Browse files
committed
feat: 现在中间件捕获异常时将触发回调而不是直接进行异常记录
1 parent 0a2868f commit 7bd8705

File tree

4 files changed

+54
-19
lines changed

4 files changed

+54
-19
lines changed

global.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
22
"msbuild-sdks": {
3-
"MSTest.Sdk": "3.6.4"
3+
"MSTest.Sdk": "3.7.2"
44
}
55
}

src/Cuture.AspNetCore.ResponseAutoWrapper/Cuture.AspNetCore.ResponseAutoWrapper.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
<IsPackable>true</IsPackable>
1717
<GenerateDocumentationFile>true</GenerateDocumentationFile>
1818

19-
<Version>1.2.2</Version>
19+
<Version>1.2.3</Version>
2020
<Description>Response and exception automatic wrapper for `asp.net core` to provide a consistent response content format for `Action`. 用于`asp.net core`的响应和异常自动包装器,使`Action`提供一致的响应内容格式。</Description>
2121

2222
<PackageIdPrefix>Cuture.AspNetCore.ResponseAutoWrapper</PackageIdPrefix>

src/Cuture.AspNetCore.ResponseAutoWrapper/ResponseAutoWrapMiddleware.cs

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ internal class ResponseAutoWrapMiddleware
2626

2727
private readonly ILogger _logger;
2828

29+
private readonly ResponseAutoWrapMiddlewareOptions.MiddlewareExceptionCaptured _middlewareExceptionCaptured;
30+
2931
private readonly RequestDelegate _next;
3032

3133
private readonly bool _notCatchExceptions;
@@ -90,6 +92,7 @@ public ResponseAutoWrapMiddleware(RequestDelegate next,
9092
_notCatchExceptions = !options.CatchExceptions;
9193
_throwCaughtExceptions = options.ThrowCaughtExceptions;
9294
_ignoreOptionsRequest = options.IgnoreOptionsRequest;
95+
_middlewareExceptionCaptured = options.OnMiddlewareExceptionCaptured ?? LogMiddlewareException;
9396

9497
var delegateCollection = GetService<ResponseAutoWrapperWorkDelegateCollection>();
9598

@@ -123,22 +126,7 @@ public async Task InvokeAsync(HttpContext context)
123126
throw;
124127
}
125128

126-
if (!_throwCaughtExceptions)
127-
{
128-
//不抛出异常时,记录异常
129-
var request = context.Request;
130-
//https://github.com/dotnet/aspnetcore/tree/8dd33378697e6f8ca89116170ec3046c185724b6/src/Hosting/Hosting/src/Internal/HostingRequestStartingLog.cs
131-
_logger.LogError(ex, "Request error {Protocol} {Method} {Scheme}://{Host}{PathBase}{Path}{QueryString} {ContentType} {ContentLength}",
132-
request.Protocol,
133-
request.Method,
134-
request.Scheme,
135-
request.Host.Value,
136-
request.PathBase.Value,
137-
request.Path.Value,
138-
request.QueryString.Value,
139-
request.ContentType ?? string.Empty,
140-
request.ContentLength.HasValue ? request.ContentLength.ToString() : string.Empty);
141-
}
129+
var doesExceptionWrapped = false;
142130

143131
//响应未开始,则包装响应
144132
if (!context.Response.HasStarted
@@ -148,6 +136,7 @@ public async Task InvokeAsync(HttpContext context)
148136
if (response is not null)
149137
{
150138
await WriteResponseWithFormatterAsync(context, response);
139+
doesExceptionWrapped = true;
151140
}
152141
}
153142
else //无法对响应进行包装,此时强制向上层抛出异常
@@ -159,6 +148,10 @@ public async Task InvokeAsync(HttpContext context)
159148
{
160149
throw;
161150
}
151+
else //不抛出异常时,触发回调
152+
{
153+
_middlewareExceptionCaptured(context.Request, ex, doesExceptionWrapped);
154+
}
162155
}
163156
finally
164157
{
@@ -178,6 +171,31 @@ public async Task InvokeAsync(HttpContext context)
178171

179172
#endregion Public 方法
180173

174+
#region Private 方法
175+
176+
/// <summary>
177+
/// 记录中间件异常
178+
/// </summary>
179+
/// <param name="request">出现异常的请求</param>
180+
/// <param name="exception">异常</param>
181+
/// <param name="hasExceptionWrapped">异常是否已包装</param>
182+
private void LogMiddlewareException(HttpRequest request, Exception exception, in bool hasExceptionWrapped)
183+
{
184+
//https://github.com/dotnet/aspnetcore/tree/8dd33378697e6f8ca89116170ec3046c185724b6/src/Hosting/Hosting/src/Internal/HostingRequestStartingLog.cs
185+
_logger.LogError(exception, "Request error {Protocol} {Method} {Scheme}://{Host}{PathBase}{Path}{QueryString} {ContentType} {ContentLength}",
186+
request.Protocol,
187+
request.Method,
188+
request.Scheme,
189+
request.Host.Value,
190+
request.PathBase.Value,
191+
request.Path.Value,
192+
request.QueryString.Value,
193+
request.ContentType ?? string.Empty,
194+
request.ContentLength.HasValue ? request.ContentLength.ToString() : string.Empty);
195+
}
196+
197+
#endregion Private 方法
198+
181199
#region Internal
182200

183201
private static MediaTypeCollection? CreateMediaTypeCollection(IList<MediaTypeHeaderValue> parsedAcceptValues)

src/Cuture.AspNetCore.ResponseAutoWrapper/ResponseAutoWrapMiddlewareOptions.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using System;
22
using System.Linq;
3-
3+
using Microsoft.AspNetCore.Http;
44
using Microsoft.AspNetCore.Mvc.Formatters;
55

66
namespace Cuture.AspNetCore.ResponseAutoWrapper;
@@ -10,6 +10,18 @@ namespace Cuture.AspNetCore.ResponseAutoWrapper;
1010
/// </summary>
1111
public class ResponseAutoWrapMiddlewareOptions
1212
{
13+
#region Public 委托
14+
15+
/// <summary>
16+
/// 中间件异常已捕获
17+
/// </summary>
18+
/// <param name="request">出现异常的请求</param>
19+
/// <param name="exception">异常</param>
20+
/// <param name="doesExceptionWrapped">异常是否已包装</param>
21+
public delegate void MiddlewareExceptionCaptured(HttpRequest request, Exception exception, in bool doesExceptionWrapped);
22+
23+
#endregion Public 委托
24+
1325
#region Public 属性
1426

1527
/// <summary>
@@ -32,6 +44,11 @@ public class ResponseAutoWrapMiddlewareOptions
3244
/// </summary>
3345
public bool IgnoreOptionsRequest { get; set; } = true;
3446

47+
/// <summary>
48+
/// 在中间件已捕获异常时的回调
49+
/// </summary>
50+
public MiddlewareExceptionCaptured? OnMiddlewareExceptionCaptured { get; set; }
51+
3552
/// <summary>
3653
/// 是否将捕获到的异常抛出给上层中间件<para/>
3754
/// default is <see langword="false"/>

0 commit comments

Comments
 (0)