using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using StackExchange.Profiling.Internal;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using WIDESEA_Core.Helper;
using WIDESEA_Core.LogHelper;
namespace WIDESEA_Core.Middlewares
{
///
/// 记录请求和响应数据
///
public class ApiLogMiddleware
{
///
///
///
private readonly RequestDelegate _next;
public ApiLogMiddleware(RequestDelegate next, ILogger logger)
{
_next = next;
}
//todo
///
/// API日志中间件,用于处理HTTP请求和响应的日志记录
///
///
/// 1. 检查系统过期时间,若过期则返回500错误
/// 2. 仅处理包含"api"路径的请求
/// 3. 记录请求和响应数据到日志系统
/// 4. 支持通过配置忽略特定URL的日志记录
///
/// 当前HTTP上下文
/// 异步任务
public async Task InvokeAsync(HttpContext context)
{
if (App.ExpDateTime != null && (DateTime.Now - App.ExpDateTime.GetValueOrDefault()).TotalSeconds > 0)
{
context.Response.StatusCode = HttpStatusCode.InternalServerError.ObjToInt();
context.Response.ContentType = "application/json";
var json = new WebResponseContent();
json.Message = HttpStatusCode.InternalServerError.ToString();//错误信息
json.Code = 500;//500异常
StreamWriter streamWriter = new StreamWriter(context.Response.Body);
await streamWriter.WriteAsync(json.Serialize());
return;
}
// 过滤,只有接口
if (context.Request.Path.Value?.Contains("api") ?? false)
{
context.Request.EnableBuffering();
Stream originalBody = context.Response.Body;
string requestParam = string.Empty;
string responseParam = string.Empty;
try
{
string? apiIgnore = AppSettings.GetValue("ApiLogIgnore")?.ToString();
string[] ignoreUrls = !string.IsNullOrEmpty(apiIgnore) ? apiIgnore.Split(",") : new string[] { "get" };
(context.RequestServices.GetService(typeof(RequestLogModel)) as RequestLogModel).RequestDate = DateTime.Now;
try
{
// 存储请求数据
requestParam = RequestDataLog(context);
context.Request.Body.Position = 0;
}
catch { }
using MemoryStream ms = new();
context.Response.Body = ms;
await _next(context);
try
{
// 存储响应数据
responseParam = ResponseDataLog(context.Response);
}
catch { }
ms.Position = 0;
await ms.CopyToAsync(originalBody);
if (!ignoreUrls.Any(x => context.Request.Path.Value?.Contains(x) ?? false))
{
Logger.Add(requestParam, responseParam);
}
}
catch (Exception ex)
{
// 记录异常
}
finally
{
context.Response.Body = originalBody;
}
}
else
{
await _next(context);
}
}
private string RequestDataLog(HttpContext context)
{
var request = context.Request;
var sr = new StreamReader(request.Body);
object obj = new
{
QueryString = request.QueryString.ToString(),
BodyData = sr.ReadToEndAsync().Result
};
string data = JsonConvert.SerializeObject(obj);
request.Body.Position = 0;
return data;
}
private string ResponseDataLog(HttpResponse response)
{
response.Body.Position = 0;
using StreamReader stream = new StreamReader(response.Body, leaveOpen: true);
string body = stream.ReadToEnd();
response.Body.Position = 0;
return body;
}
}
}