基于此处接受的答案
How to read ASP.NET Core Response.Body?
我稍微修改了解决方案并让它工作。我想分享我关于如何记录每个传入请求和每个传出响应的解决方案。
如果您认为此解决方案容易出错或是否可以改进,请发表评论!
对于请求记录:
public class RequestLoggingMiddleware
{
private readonly RequestDelegate requestDelegate;
private readonly ILogger<RequestLoggingMiddleware> logger;
public RequestLoggingMiddleware(RequestDelegate requestDelegate, ILogger<RequestLoggingMiddleware> logger)
{
this.requestDelegate = requestDelegate;
this.logger = logger;
}
public async Task InvokeAsync(HttpContext httpContext)
{
await LogRequest(httpContext.Request);
await requestDelegate(httpContext);
}
private async Task LogRequest(HttpRequest httpRequest)
{
StringBuilder stringBuilder = new StringBuilder();
AppendMethod(httpRequest, stringBuilder);
AppendPath(httpRequest, stringBuilder);
AppendContentType(httpRequest, stringBuilder);
AppendHeaders(httpRequest, stringBuilder);
AppendParams(httpRequest, stringBuilder);
AppendQueries(httpRequest, stringBuilder);
await AppendBody(httpRequest, stringBuilder);
logger.LogTrace(stringBuilder.ToString());
}
private void AppendMethod(HttpRequest httpRequest, StringBuilder stringBuilder)
{
stringBuilder.AppendLine($"Method: {httpRequest.Method}");
}
private void AppendPath(HttpRequest httpRequest, StringBuilder stringBuilder)
{
stringBuilder.AppendLine($"Path: {httpRequest.Path.Value}");
}
private void AppendContentType(HttpRequest httpRequest, StringBuilder stringBuilder)
{
string contentType = httpRequest.ContentType;
if (!string.IsNullOrEmpty(contentType))
{
stringBuilder.AppendLine($"Content type: {contentType}");
}
}
private void AppendHeaders(HttpRequest httpRequest, StringBuilder stringBuilder)
{
AppendCollection(httpRequest.Headers, "Headers", stringBuilder);
}
private void AppendParams(HttpRequest httpRequest, StringBuilder stringBuilder)
{
AppendCollection(httpRequest.RouteValues, "Params", stringBuilder);
}
private void AppendQueries(HttpRequest httpRequest, StringBuilder stringBuilder)
{
AppendCollection(httpRequest.Query, "Queries", stringBuilder);
}
private void AppendCollection<TKey, TValue>(
IEnumerable<KeyValuePair<TKey, TValue>> collection,
string collectionName,
StringBuilder stringBuilder)
{
if (collection.Any())
{
stringBuilder.AppendLine($"{collectionName}:");
foreach ((TKey key, TValue value) in collection)
{
stringBuilder.AppendLine($"\t{key}: {value}");
}
}
}
private async Task AppendBody(HttpRequest httpRequest, StringBuilder stringBuilder)
{
httpRequest.EnableBuffering();
ReadResult bodyReadResult = await httpRequest.BodyReader.ReadAsync();
ReadOnlySequence<byte> bodyBuffer = bodyReadResult.Buffer;
if (bodyBuffer.Length > 0)
{
byte[] bodyBytes = bodyBuffer.ToArray();
string bodyText = Encoding.UTF8.GetString(bodyBytes);
stringBuilder.AppendLine($"Body: {bodyText}");
}
httpRequest.Body.Seek(0, SeekOrigin.Begin);
}
}
响应记录有点不同
public class ResponseLoggingMiddleware
{
private readonly RequestDelegate requestDelegate;
private readonly ILogger<RequestLoggingMiddleware> logger;
public ResponseLoggingMiddleware(RequestDelegate requestDelegate, ILogger<RequestLoggingMiddleware> logger)
{
this.requestDelegate = requestDelegate;
this.logger = logger;
}
public async Task InvokeAsync(HttpContext httpContext)
{
HttpResponse httpResponse = httpContext.Response;
Stream originalBody = httpResponse.Body;
try
{
using (MemoryStream memoryStream = new MemoryStream())
{
httpResponse.Body = memoryStream;
await requestDelegate(httpContext);
await LogResponse(httpContext.Response, originalBody, memoryStream);
}
}
finally
{
httpContext.Response.Body = originalBody;
}
}
private async Task LogResponse(HttpResponse httpResponse, Stream originalBody, MemoryStream memoryStream)
{
StringBuilder stringBuilder = new StringBuilder();
AppendStatusCode(httpResponse, stringBuilder);
AppendContentType(httpResponse, stringBuilder);
await AppendBody(httpResponse, stringBuilder, originalBody, memoryStream);
logger.LogTrace(stringBuilder.ToString());
}
private void AppendStatusCode(HttpResponse httpResponse, StringBuilder stringBuilder)
{
stringBuilder.AppendLine($"Status code: {httpResponse.StatusCode}");
}
private void AppendContentType(HttpResponse httpResponse, StringBuilder stringBuilder)
{
string contentType = httpResponse.ContentType;
if (!string.IsNullOrEmpty(contentType))
{
stringBuilder.AppendLine($"Content type: {contentType}");
}
}
private async Task AppendBody(HttpResponse httpResponse, StringBuilder stringBuilder, Stream originalBody, MemoryStream memoryStream)
{
httpResponse.Body.Seek(0, SeekOrigin.Begin);
StreamReader streamReader = new StreamReader(memoryStream);
string bodyText = await streamReader.ReadToEndAsync();
if (bodyText.Length > 0)
stringBuilder.AppendLine($"Body: {bodyText}");
httpResponse.Body.Seek(0, SeekOrigin.Begin);
await memoryStream.CopyToAsync(originalBody);
}
}