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