RecordAPIOperationMiddleware.cs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. using Aspose.Words;
  2. using NPOI.HSSF.Record;
  3. using OASystem.Domain.Attributes;
  4. using OASystem.Domain.Entities.Customer;
  5. using OASystem.Infrastructure.Repositories.CRM;
  6. using System.ComponentModel.DataAnnotations;
  7. using System.Diagnostics;
  8. using XAct;
  9. using static Google.Protobuf.Reflection.SourceCodeInfo.Types;
  10. namespace OASystem.API.Middlewares
  11. {
  12. /// <summary>
  13. /// 指定API操作记录信息
  14. /// </summary>
  15. public class RecordAPIOperationMiddleware
  16. {
  17. private readonly RequestDelegate _next;
  18. private readonly HttpClient _httpClient;
  19. private readonly IConfiguration _config;
  20. private readonly SqlSugarClient _sqlSugar;
  21. public RecordAPIOperationMiddleware(RequestDelegate next, IConfiguration config, HttpClient httpClient, SqlSugarClient sqlSugar)
  22. {
  23. _next = next;
  24. _httpClient = httpClient;
  25. _config = config;
  26. _sqlSugar = sqlSugar;
  27. }
  28. public async Task InvokeAsync(HttpContext context)
  29. {
  30. // 启用请求体流的缓冲,允许多次读取
  31. context.Request.EnableBuffering();
  32. // 读取请求体内容
  33. var requestBodyText = await ReadRequestBody(context.Request);
  34. // 检查控制器方法是否使用了自定义属性
  35. var endpoint = context.GetEndpoint();
  36. var apiLogAttribute = endpoint?.Metadata?.GetMetadata<ApiLogAttribute>();
  37. if (apiLogAttribute != null)
  38. {
  39. var startTime = DateTime.UtcNow;
  40. // 保存原始响应体流
  41. var originalResponseBody = context.Response.Body;
  42. // 创建一个新的内存流来捕获响应体
  43. using var responseMemoryStream = new MemoryStream();
  44. context.Response.Body = responseMemoryStream;
  45. // 调用下一个中间件
  46. await _next(context);
  47. // 读取响应体内容
  48. var responseBodyText = await new StreamReader(responseMemoryStream).ReadToEndAsync();
  49. // 重置响应体流的位置
  50. responseMemoryStream.Position = 0;
  51. // 将响应体内容写回原始响应体流
  52. await responseMemoryStream.CopyToAsync(originalResponseBody);
  53. // 记录请求结束时间
  54. var endTime = DateTime.UtcNow;
  55. // 计算耗时
  56. var duration = (long)(endTime - startTime).TotalMilliseconds;
  57. int portType = 1;
  58. var logInfo = new Crm_TableOperationRecord() {
  59. TableName = apiLogAttribute.TableName,
  60. PortType = portType,
  61. OperationItem = apiLogAttribute.OperationEnum,
  62. DataId = apiLogAttribute.DataId,
  63. RequestUrl = context.Request.Path,
  64. RequestParam = requestBodyText,
  65. ReturnResult = responseBodyText,
  66. Elapsed = duration,
  67. Status = context.Response.StatusCode.ToString(),
  68. };
  69. // 存储到数据库
  70. await _sqlSugar.Insertable(logInfo).ExecuteCommandAsync();
  71. }
  72. else
  73. {
  74. // 调用下一个中间件
  75. await _next(context);
  76. }
  77. }
  78. private async Task<string> ReadRequestBody(HttpRequest request)
  79. {
  80. request.EnableBuffering();
  81. // 读取请求体内容
  82. using var reader = new StreamReader(request.Body, Encoding.UTF8, true, 1024, true);
  83. var requestBodyText = await reader.ReadToEndAsync();
  84. // 重置请求体流的位置
  85. request.Body.Position = 0;
  86. return requestBodyText;
  87. }
  88. private async Task<string> GetExternalIp()
  89. {
  90. var response = await _httpClient.GetAsync("https://ifconfig.me");
  91. response.EnsureSuccessStatusCode();
  92. return await response.Content.ReadAsStringAsync();
  93. }
  94. private async Task<string> GetIpLocation(string ip)
  95. {
  96. var response = await _httpClient.GetAsync($"https://ipinfo.io/{ip}/json");
  97. response.EnsureSuccessStatusCode();
  98. var json = await response.Content.ReadAsStringAsync();
  99. var ipInfo = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(json);
  100. return $"{ipInfo.country}, {ipInfo.city}";
  101. }
  102. }
  103. }