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}
================================================================================"
);
}
}
}