90 lines
3.4 KiB
C#
90 lines
3.4 KiB
C#
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.Extensions.Logging;
|
|
using System;
|
|
using System.IO;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using VOL.Core.Enums;
|
|
using VOL.Core.Services;
|
|
|
|
namespace VOL.Core.Middleware
|
|
{
|
|
/// <summary>
|
|
/// 接口输入输出日志中间件
|
|
/// </summary>
|
|
public class RequestResponseLoggingMiddleware
|
|
{
|
|
private readonly RequestDelegate _next;
|
|
private readonly ILogger<RequestResponseLoggingMiddleware> _logger;
|
|
|
|
public RequestResponseLoggingMiddleware(RequestDelegate next, ILogger<RequestResponseLoggingMiddleware> logger)
|
|
{
|
|
_next = next;
|
|
_logger = logger;
|
|
}
|
|
|
|
public async Task InvokeAsync(HttpContext context)
|
|
{
|
|
DateTime now = DateTime.Now;
|
|
|
|
// Log the request
|
|
var request = await HttpRequestResponseFormat.FormatRequest(context.Request);
|
|
_logger.LogInformation($"HTTP Request Information:{Environment.NewLine}{now} {request}");
|
|
|
|
// Copy a pointer to the original response body stream
|
|
var originalBodyStream = context.Response.Body;
|
|
|
|
// Create a new memory stream to hold the response body
|
|
using (var responseBody = new MemoryStream())
|
|
{
|
|
context.Response.Body = responseBody;
|
|
await _next(context);
|
|
|
|
// Log the response
|
|
string response = await HttpRequestResponseFormat.FormatResponse(context.Response);
|
|
Logger.OK(LoggerType.Info, request, response);
|
|
_logger.LogInformation($"HTTP Response Information:{Environment.NewLine}{now} {response}");
|
|
|
|
// Copy the contents of the new memory stream (which contains the response) to the original stream
|
|
await responseBody.CopyToAsync(originalBodyStream);
|
|
}
|
|
}
|
|
}
|
|
|
|
public sealed class HttpRequestResponseFormat
|
|
{
|
|
public static async Task<string> FormatRequest(HttpRequest request)
|
|
{
|
|
request.EnableBuffering();
|
|
|
|
// 二进制内容判断可保留
|
|
if (request.ContentType != null &&
|
|
(request.ContentType.Contains("multipart/form-data") || request.ContentType.Contains("application/octet-stream")))
|
|
{
|
|
return $"{request.Scheme} {request.Host}{request.Path} {request.QueryString} [二进制数据不可读]";
|
|
}
|
|
|
|
using var reader = new StreamReader(request.Body, Encoding.UTF8, leaveOpen: true);
|
|
var bodyAsText = await reader.ReadToEndAsync();
|
|
request.Body.Position = 0;
|
|
|
|
return $"{request.Scheme} {request.Host}{request.Path} {request.QueryString} {bodyAsText}";
|
|
}
|
|
|
|
public static async Task<string> FormatResponse(HttpResponse response)
|
|
{
|
|
response.Body.Seek(0, SeekOrigin.Begin);
|
|
|
|
if (response.ContentType != null && response.ContentType.Contains("application/octet-stream"))
|
|
{
|
|
return $"StatusCode: {response.StatusCode}, Body: 二进制数据不可读";
|
|
}
|
|
|
|
using var reader = new StreamReader(response.Body, Encoding.UTF8, leaveOpen: true);
|
|
var text = await reader.ReadToEndAsync();
|
|
response.Body.Seek(0, SeekOrigin.Begin);
|
|
|
|
return $"StatusCode: {response.StatusCode}, Body: {text}";
|
|
}
|
|
}
|
|
} |