.NET 6 日志记录中间件

.NET 6 Logging middleware

我们正在尝试创建一个中间件,允许您登录到 HTTP 响应正文的外部服务。

我们尝试用 MemoryStream 替换它,但是当我们尝试读取它时,它却被关闭了。

有人可以帮助我们吗?

提前致谢

代码如下:

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;
        }
    }
}

在以下 Whosebug 问题中对此有很多很好的讨论:

因为这个当前问题调用 out.NET 6,所以我会特别关注这个答案,它切断了很多以前的解决方法:

综上所述,由于该问题中概述的各种原因(缓冲区、转换、泄漏、数据大小),管理请求和响应流是一个 non-trivial 挑战。根据您需要对日志记录参数施加的控制级别,您可能会发现仅使用 built-in HttpLoggingMiddleware.

是有益的

可以注册:

builder.Services.AddHttpLogging(opts => 
{
    opts .LoggingFields = HttpLoggingFields.ResponseBody;
});

然后使用 app.UseHttpLogging() 添加到管道中,此时您可以连接到 ASP NET Core ILogger 以获取响应正文作为日志记录实现的一部分:

https://source.dot.net/#Microsoft.AspNetCore.HttpLogging/HttpLoggingExtensions.cs,27

感谢开源,如果您需要构建更强大或更深入的钩子,您可以在此处深入了解 Microsoft 如何实现该中间件:https://source.dot.net/#Microsoft.AspNetCore.HttpLogging/HttpLoggingMiddleware.cs,35c5841599b94285

关键要素是 IHttpResponseBodyFeature 实现的使用,它是 not heavily documented 但它是连接到 request/response 管道那部分的抽象点,因为 3.x. Rick Strahl 在他的博客中有一个 post,其中显示了那里所需的一些实施深度:

https://weblog.west-wind.com/posts/2020/Mar/29/Content-Injection-with-Response-Rewriting-in-ASPNET-Core-3x