【问题标题】:Can not read Response.Body from server in .Net5无法从 .Net5 中的服务器读取 Response.Body
【发布时间】:2021-12-08 01:55:36
【问题描述】:

我在 Api 网关 .Net5 的中间件中跟踪请求/响应日志,我可以读取 Request.Body,但是,我不了解响应的正文,如下所示

 `�      <�_O�0G��r_����%>�"A�8��[��Im���
�w7n��{rO��/�կZ~y����36������rNIJ��d�w��\�'�����|w-�!�OR#Q�fi�X��   G��Sg�`��X@��{��KE�k�T3Zj%5N�@���+��SY��[�׊C(w� �·��@"�E���UnM�}��Jc�k�����F����#��$q�O(�.tÃ�c�ӕW����  �� ID�P`

在这里分享我的读取响应代码

              string responseBody = string.Empty;
                var originalBodyStream = context?.Response.Body;

                //Create a new memory stream...
                using (var responseStream = new MemoryStream())
                {
                        context.Response.Body = responseStream;
                        await _next.Invoke(context);
                        context.Response.Body.Seek(0, SeekOrigin.Begin);
                        responseBody = new StreamReader(context.Response.Body).ReadToEnd();
                        context.Response.Body.Seek(0, SeekOrigin.Begin);
                        await responseStream.CopyToAsync(originalBodyStream);
                }

这是我的请求标头

{
    "Accept":"application/json, text/plain, */*",
    "Accept-Encoding":"gzip",
    "Accept-Language":"en-GB,en-US;q=0.9,en;q=0.8",
    "Connection":"Keep-Alive",
    "Content-Length":"2",
    "Content-Type":"application/json;charset=UTF-8",
   }

【问题讨论】:

  • 这显然是一个二进制文件(一个 GZIP 文件),而不是文本。 StreamReader 仅用于文本输入。
  • "Content-Length":"2",一定是错的。
  • @PoulBak 它由浏览器创建
  • @PanagiotisKanavos 非常感谢,现在我可以使用 SharpZipLib 包阅读
  • 您不必这样做。 ASP.NET Core 已经支持压缩和解压缩。它已经支持请求和响应日志记录。在响应已经压缩后,您自己的中间件似乎运行得太晚了

标签: c# asp.net-core .net-5 api-gateway asp.net-core-middleware


【解决方案1】:

您不必编写自己的响应日志记录代码。 ASP.NET Core 已经支持HTTP Logging。它也支持使用多种算法的响应压缩,包括 SharpZipLib 不支持的 Brotli。

To enable logging 只需调用app.UseHttpLogging()

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseHttpLogging();
...

请求和响应将被记录为来自Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware 源的Information 消息。可以使用 Logging 配置,通过代码或配置设置来配置这些消息的目的地。

ASP.NET Core 没有内置的文件提供程序。最常见的选项之一是使用Serilog,它可以配置为将来自不同来源的消息记录到不同的文件中:

    public static int Main(string[] args)
    {
        Log.Logger = new LoggerConfiguration()
            .MinimumLevel.Override("Microsoft", LogEventLevel.Information)
            .Enrich.FromLogContext()
            .WriteTo.Console()
            .WriteTo.File("log.txt")
            .CreateLogger();
...

CreateHostBuilder()

public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .UseSerilog() // <-- Add this line
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });

ASP.NET Core Serilog 集成还包括Request logging

通过将参数传递给File,可以通过例如日志级别记录到不同的文件,例如:

        .WriteTo.Console()
        .WriteTo.File("log.txt",LogEventLevel.Information)
        .WriteTo.File("errors.txt",LogEventLevel.Error)

可以使用sub-loggers 配置登录到不同的接收器:

.WriteTo.Logger(lc => lc
    .Filter.ByIncludingOnly(Matching.FromSource<Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware>())
    .WriteTo.File("http.txt"))

【讨论】:

    【解决方案2】:

    我可以使用 SharpZipLib 包阅读, 这段代码对我有用

                GZipInputStream unGzipStream = new GZipInputStream(response.Body);
                var responseBodytxt = new StreamReader(unGzipStream).ReadToEnd();
                response.Body.Seek(0, SeekOrigin.Begin);
    

    【讨论】:

    • 虽然这段代码可以回答这个问题,但最好在不介绍其他代码的情况下解释它是如何解决问题的,以及为什么要使用它。从长远来看,纯代码答案没有用处。
    • 这不是一个好的解决方案。 ASP.NET Core 已经支持压缩和request/response logging。它也支持其他压缩算法,这些算法不适用于 SharpZipLib。您真正需要做的就是使用services.AddHttpLogging
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-07
    • 1970-01-01
    • 2016-03-10
    • 2012-03-30
    相关资源
    最近更新 更多