我有一个带有请求和响应日志记录中间件的.NET Core Web API项目。我在文件中的Configure
方法中注册了两个中间件Startup
文件
app.UseMiddleware<RequestLoggingMiddleware>();
app.UseMiddleware<ResponseLoggingMiddleware>();
现在,我只是尝试记录正文,请求记录似乎工作正常
public class RequestLoggingMiddleware
{
private readonly RequestDelegate requestDelegate;
public RequestLoggingMiddleware(RequestDelegate requestDelegate)
{
this.requestDelegate = requestDelegate;
}
public async Task InvokeAsync(HttpContext httpContext)
{
HttpRequest httpRequest = httpContext.Request;
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);
Console.WriteLine(bodyText);
}
// Reset
httpRequest.Body.Seek(0, SeekOrigin.Begin);
await requestDelegate(httpContext);
}
}
我的响应记录中间件无权访问BodyReader
。我尝试使用此代码
public class ResponseLoggingMiddleware
{
private readonly RequestDelegate requestDelegate;
public ResponseLoggingMiddleware(RequestDelegate requestDelegate)
{
this.requestDelegate = requestDelegate;
}
public async Task InvokeAsync(HttpContext httpContext)
{
await requestDelegate(httpContext);
Stream responseBody = httpContext.Response.Body;
using (StreamReader reader = new StreamReader(responseBody))
{
string bodyText = await reader.ReadToEndAsync();
// Reset
responseBody.Seek(0, SeekOrigin.Begin);
Console.WriteLine(bodyText);
}
}
}
但不幸的是我得到了这个例外
System.ArgumentException:流不可读。
有人知道如何解决吗?
根据此处的正确答案
如何阅读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);
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句