w4r*_*rcT 4 .net-core asp.net-core .net-6.0
We are trying to create a middleware that allows you to log in to an external service the body of an HTTP response.
We tried replacing it with a MemoryStream, but when we try to read it it turns out to be closed.
Could anyone help us?
Thanks in advance
Here is the code:
public class LogMiddleware
{
private readonly RequestDelegate _next;
public LogMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
var originBody = context.Response.Body;
try
{
var memStream = new MemoryStream();
context.Response.Body = memStream;
await _next(context).ConfigureAwait(false);
memStream.Position = 0;
var responseBody = new StreamReader(memStream).ReadToEnd();
var memoryStreamModified = new MemoryStream();
var sw = new StreamWriter(memoryStreamModified);
sw.Write(responseBody);
sw.Flush();
memoryStreamModified.Position = 0;
await memoryStreamModified.CopyToAsync(originBody).ConfigureAwait(false);
}
finally
{
context.Response.Body = originBody;
}
}
}
Run Code Online (Sandbox Code Playgroud)
在以下 StackOverflow 问题中对此有很多很好的讨论:How to read ASP.NET Core Response.Body?
因为当前的问题呼唤.NET 6,所以我特别关注这个答案,它突破了许多以前的解决方法: https: //stackoverflow.com/a/70477179/13374279
总而言之,由于该问题中概述的各种原因(缓冲区、转换、泄漏、数据大小),管理请求和响应流是一项不小的挑战。根据您需要对日志记录参数施加的控制级别,您可能会发现仅使用内置的 HttpLoggingMiddleware是有益的。
它可以通过以下方式注册:
builder.Services.AddHttpLogging(opts =>
{
opts .LoggingFields = HttpLoggingFields.ResponseBody;
});
Run Code Online (Sandbox Code Playgroud)
然后使用 添加到管道app.UseHttpLogging(),此时您可以连接到 ASP NET CoreILogger以获取响应正文作为日志记录实现的一部分:
https://source.dot.net/#Microsoft.AspNetCore.HttpLogging/HttpLoggingExtensions.cs,27
感谢开源,如果您需要构建更强大或更深入的钩子,您可以在此处深入了解 Microsoft 如何实现该中间件:https://source.dot.net/#Microsoft.AspNetCore.HttpLogging/HttpLoggingMiddleware.cs,35c5841599b94285
关键元素是实现的使用IHttpResponseBodyFeature,虽然没有大量文档记录,但它是自 3.x 以来连接到请求/响应管道的该部分的抽象点。Rick Strahl 在他的博客中发表了一篇文章,展示了那里所需的一些实施深度:
| 归档时间: |
|
| 查看次数: |
6355 次 |
| 最近记录: |