using Microsoft.AspNetCore.Http;
|
using Microsoft.Extensions.Logging;
|
using Newtonsoft.Json;
|
using Org.BouncyCastle.Asn1.Ocsp;
|
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
|
{
|
/// <summary>
|
/// 记录请求和响应数据
|
/// </summary>
|
public class ApiLogMiddleware
|
{
|
/// <summary>
|
///
|
/// </summary>
|
private readonly RequestDelegate _next;
|
private readonly ILogger<ApiLogMiddleware> _logger;
|
|
public ApiLogMiddleware(RequestDelegate next, ILogger<ApiLogMiddleware> logger)
|
{
|
_next = next;
|
_logger = logger;
|
}
|
|
//todo
|
public async Task InvokeAsync(HttpContext context)
|
{
|
//if (App.ExpDateTime != null)
|
//{
|
// if ((DateTime.Now - App.ExpDateTime.GetValueOrDefault()).TotalSeconds > 0)
|
// {
|
// await ReturnExpiredResponse(context, "系统已过期,请联系管理员");
|
// return;
|
// }
|
// //var Hours = (App.ExpDateTime.GetValueOrDefault() - DateTime.Now).TotalHours;
|
// //if (Hours < 72)
|
// //{
|
// // // 记录警告日志
|
// // _logger.LogWarning($"系统即将到期,剩余时间:{Hours:F2}小时,到期时间:{App.ExpDateTime.GetValueOrDefault():yyyy-MM-dd HH:mm:ss}");
|
|
// // // 在响应头中添加到期提示
|
// // context.Response.Headers.Add("X-Expiration-Warning",
|
// // $"系统将在 {Hours:F2} 小时后到期 ({App.ExpDateTime.GetValueOrDefault():yyyy-MM-dd HH:mm:ss})");
|
|
// // // 如果需要直接返回提示信息,取消下面的注释
|
// // await ReturnExpirationWarningResponse(context, Hours);
|
// // return;
|
// //}
|
|
//}
|
|
// 过滤,只有接口
|
if (context.Request.Path.Value?.Contains("api") ?? false)
|
{
|
if (App.ExpDateTime != null)
|
{
|
if ((DateTime.Now - App.ExpDateTime.GetValueOrDefault()).TotalSeconds > 0 && !context.Request.Path.Value.Contains("getVierificationCode") && context.Request.Path.Value != "/api/User/login")
|
{
|
await ReturnExpiredResponse(context, "系统已过期,请联系管理员");
|
return;
|
}
|
}
|
context.Request.EnableBuffering();
|
Stream originalBody = context.Response.Body;
|
string requestParam = string.Empty;
|
string responseParam = string.Empty;
|
try
|
{
|
(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 (!ShouldSkipLogging(context.Request.Path.Value))
|
Logger.Add(requestParam, responseParam);
|
}
|
catch (Exception ex)
|
{
|
// 记录异常
|
|
}
|
finally
|
{
|
context.Response.Body = originalBody;
|
}
|
}
|
else
|
{
|
await _next(context);
|
}
|
}
|
|
/// <summary>
|
/// 返回过期响应
|
/// </summary>
|
private async Task ReturnExpiredResponse(HttpContext context, string message)
|
{
|
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
|
context.Response.ContentType = "application/json; charset=utf-8";
|
context.Response.Headers.ContentType= "application/json; charset=utf-8";
|
var json = new WebResponseContent
|
{
|
Message = message,
|
Code = 500
|
};
|
|
var jsonString = JsonConvert.SerializeObject(json);
|
await context.Response.WriteAsync(jsonString);
|
}
|
/// <summary>
|
/// 返回到期警告响应(可选)
|
/// </summary>
|
private async Task ReturnExpirationWarningResponse(HttpContext context, double hoursRemaining)
|
{
|
context.Response.StatusCode = (int)HttpStatusCode.OK;
|
context.Response.ContentType = "application/json";
|
|
var expirationDate = App.ExpDateTime.GetValueOrDefault();
|
var response = new
|
{
|
Code = 200,
|
Message = "系统即将到期警告",
|
Data = new
|
{
|
HoursRemaining = hoursRemaining,
|
ExpirationDate = expirationDate,
|
FormattedMessage = $"系统将在 {Math.Ceiling(hoursRemaining)} 小时后到期,到期时间:{expirationDate:yyyy-MM-dd HH:mm:ss}。请联系管理员续期。"
|
},
|
Warning = true
|
};
|
|
var jsonString = JsonConvert.SerializeObject(response);
|
await context.Response.WriteAsync(jsonString);
|
}
|
|
/// <summary>
|
/// 判断是否跳过日志记录
|
/// </summary>
|
private bool ShouldSkipLogging(string path)
|
{
|
if (string.IsNullOrEmpty(path)) return false;
|
|
var skipKeywords = new[] { "get", "Get", "query", "Query", "DownLoadApp", "downLoadApp", "UploadApp", "uploadApp" };
|
return skipKeywords.Any(keyword => path.Contains(keyword, StringComparison.OrdinalIgnoreCase));
|
}
|
|
private string RequestDataLog(HttpContext context)
|
{
|
var request = context.Request;
|
|
var sr = new StreamReader(request.Body);
|
|
object obj;
|
string bodyData = sr.ReadToEndAsync().Result;
|
if (request.ContentLength <= 100000)
|
{
|
obj = new
|
{
|
QueryString = request.QueryString.ToString(),
|
BodyData = bodyData
|
};
|
}
|
else
|
{
|
obj = new
|
{
|
QueryString = request.QueryString.ToString(),
|
BodyData = ""
|
};
|
}
|
string data = JsonConvert.SerializeObject(obj);
|
|
request.Body.Position = 0;
|
|
return data;
|
}
|
|
private string ResponseDataLog(HttpResponse response)
|
{
|
if (response.ContentLength <= 100000)
|
{
|
response.Body.Position = 0;
|
using StreamReader stream = new StreamReader(response.Body, leaveOpen: true);
|
string body = stream.ReadToEnd();
|
response.Body.Position = 0;
|
return body;
|
}
|
return "";
|
}
|
}
|
}
|