using System.Diagnostics; using System.Text; namespace Gatedge.ScanCode.Middleware { /// /// 日志中间件 /// public class ResponseLoggingMiddleware { private readonly RequestDelegate _next; private readonly ILogger _logger; /// /// 构造函数 /// /// /// public ResponseLoggingMiddleware(RequestDelegate next, ILogger logger) { _next = next; _logger = logger; } /// /// 中间件处理函数 /// /// /// public async Task Invoke(HttpContext context) { // 访问路径 var path = context.Request.Path; // 记录请求开始时间 var startTime = Stopwatch.GetTimestamp(); // 获取客户端 IP 地址(处理反向代理场景) var ipAddress = context.Connection.RemoteIpAddress?.ToString(); if (context.Request.Headers.TryGetValue("X-Forwarded-For", out var forwardedFor)) { ipAddress = forwardedFor.ToString(); } // 记录请求体(JSON) string RequestBody = string.Empty; if (context.Request.ContentType?.Contains("application/json") == true) { context.Request.EnableBuffering(); using var reader = new StreamReader(context.Request.Body, Encoding.UTF8, true, 1024, true); RequestBody = await reader.ReadToEndAsync(); context.Request.Body.Position = 0; } // 捕获原始响应流 var originalBodyStream = context.Response.Body; // 使用内存流捕获响应 using var responseBody = new MemoryStream(); context.Response.Body = responseBody; // 调用下一个中间件 await _next(context); // 记录响应体 responseBody.Seek(0, SeekOrigin.Begin); var bodyText = await new StreamReader(responseBody, Encoding.Default, true, 1024, true).ReadToEndAsync(); // 将响应复制回原始流 responseBody.Seek(0, SeekOrigin.Begin); await responseBody.CopyToAsync(originalBodyStream); context.Response.Body = originalBodyStream; // 记录请求结束时间 var endTime = Stopwatch.GetTimestamp(); // 计算请求耗时 var elapsed = (double)(endTime - startTime) / Stopwatch.Frequency * 1000.000; // 记录日志 // _logger.LogInformation( //@"Request: {Method} {Path} | IP: {IP} | Status: {StatusCode} | Time: {Elapsed}ms //RequestBody: {Request} //ResponseBody: {Response} //================================================================================", // context.Request.Method, // context.Request.Path, // ipAddress, // context.Response.Body, // elapsed, // RequestBody, // bodyText // ); // 记录日志 var method = context.Request.Method; var statusCode = context.Response.Body; _logger.LogInformation( @$"Request: {method} {path} | IP: {ipAddress} | Status: {statusCode} | Time: {elapsed}ms RequestBody: {RequestBody} ================================================================================" ); } } }