104 lines
3.8 KiB
C#
104 lines
3.8 KiB
C#
using System.Diagnostics;
|
||
using System.Text;
|
||
|
||
namespace Gatedge.ScanCode.Middleware
|
||
{
|
||
/// <summary>
|
||
/// 日志中间件
|
||
/// </summary>
|
||
public class ResponseLoggingMiddleware
|
||
{
|
||
private readonly RequestDelegate _next;
|
||
private readonly ILogger<ResponseLoggingMiddleware> _logger;
|
||
|
||
/// <summary>
|
||
/// 构造函数
|
||
/// </summary>
|
||
/// <param name="next"></param>
|
||
/// <param name="logger"></param>
|
||
public ResponseLoggingMiddleware(RequestDelegate next, ILogger<ResponseLoggingMiddleware> logger)
|
||
{
|
||
_next = next;
|
||
_logger = logger;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 中间件处理函数
|
||
/// </summary>
|
||
/// <param name="context"></param>
|
||
/// <returns></returns>
|
||
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}
|
||
================================================================================"
|
||
);
|
||
}
|
||
}
|
||
}
|