.NET 6 Logging middleware

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)

Ada*_*dam 6

在以下 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 在他的博客中发表了一篇文章,展示了那里所需的一些实施深度:

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