简体   繁体   English

记录对多个端点的请求,而无需在 ASP.NET Core 中的每个端点中进行更改

[英]Logging requests for multiple endpoints without making changes in each endpoint in ASP.NET Core

I am working on Asp.Net Core API, There are around 1000 endpoints which can have different bodies (request payload).我正在研究 Asp.Net Core API,大约有 1000 个端点可以有不同的主体(请求有效负载)。 I want to log the the incoming requests for each endpoint.我想记录每个端点的传入请求。 I dont want to go and make changes in each endpoint.我不想 go 并在每个端点中进行更改。 So Is there a way to do this?那么有没有办法做到这一点?

I have tried the below.我试过下面的。 But it logs requestBody as empty string.但它将 requestBody 记录为空字符串。 Although I get the request object value in the controller action method.虽然我在 controller 操作方法中得到了请求 object 值。 The below code is for http post.以下代码适用于 http 帖子。

public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
    // Log the request details
    _logger.LogInformation($"Request: {context.HttpContext.Request.Method} {context.HttpContext.Request.Path}");

    // Log the request body for POST requests
    if (context.HttpContext.Request.Method.Equals("POST", StringComparison.OrdinalIgnoreCase))
    {
        context.HttpContext.Request.EnableBuffering();

        // Read the request body
        using (var reader = new StreamReader(context.HttpContext.Request.Body, encoding: Encoding.UTF8, detectEncodingFromByteOrderMarks: false, leaveOpen: true))
        {
            var requestBody = await reader.ReadToEndAsync();

            // Reset the position of the request body stream
            context.HttpContext.Request.Body.Position = 0;

            _logger.LogInformation($"Request Body: {requestBody}");
        }
    }

    // Call the action method
    var resultContext = await next();

    // Perform any post-action execution logic if needed
}

I have tried this and this is working for one endpoint, but there could be many different request types so I'll end up using multiple if else and I want to avoid it, basically I'm looking for a generic solution.我已经尝试过这个并且它适用于一个端点,但是可能有许多不同的请求类型所以我最终会使用多个 if else 并且我想避免它,基本上我正在寻找一个通用的解决方案。

https://stackoverflow.com/a/67262551/6527049 https://stackoverflow.com/a/67262551/6527049

Note : I have read some articles mentioning that it can be done using middleware, but in this question I'm more interested in fixing issue in my code.注意:我读过一些文章提到它可以使用中间件来完成,但在这个问题中我更感兴趣的是修复我的代码中的问题。 Or can be fixed using ActionFilter或者可以使用 ActionFilter 修复

First of all I highly recommend to look into using existing HTTP Logging infrastructure provided by the framework , note that you can enable it conditionally with UseWhen (like it is done here or here ).首先,我强烈建议研究使用框架提供的现有 HTTP 日志记录基础设施,请注意,您可以使用UseWhen有条件地启用它(就像在此处此处完成的一样)。

If for some reason it is not sutable for you then for your problem:如果由于某种原因它不适合您,那么针对您的问题:

But it logs requestBody as empty string但它将 requestBody 记录为空字符串

There are 2 possible problems here (do not have setup to repro ATM):这里有 2 个可能的问题(没有设置来重现 ATM):

  1. EnableBuffering is called too late, try adding next middleware somewhere at the start of the pipeline (like it is done here ): EnableBuffering被调用得太晚了,尝试在管道开始的某个地方添加下一个中间件(就像它在这里完成的那样):
app.Use((context, next) =>
{
    context.Request.EnableBuffering();
    return next();
});
// ...
  1. Stream was already read, rewind the incoming stream before reading it: Stream 已被阅读,在阅读之前倒回传入的 stream:
// ...
context.HttpContext.Request.Body.Position = 0;
using (var reader = new StreamReader(context.HttpContext.Request.Body, encoding: Encoding.UTF8, detectEncodingFromByteOrderMarks: false, leaveOpen: true))
{
    var requestBody = await reader.ReadToEndAsync();

    // Reset the position of the request body stream
    context.HttpContext.Request.Body.Position = 0;

    _logger.LogInformation($"Request Body: {requestBody}");
}

Also check out this answer .另请查看此答案

I tested your code, and it seems to work well.我测试了你的代码,它似乎运行良好。 Do you send your request as JSON with the body?您是否将您的请求作为 JSON 与正文一起发送? Could you please verify the Content-Type header?您能否验证内容类型 header?

在此处输入图像描述

Here is your code with minor modifications.这是您的代码,稍作修改。

class ActionFilterExample: class 动作过滤器示例:

public class ActionFilterExample : IAsyncActionFilter
{
    private readonly ILogger _logger;

    public ActionFilterExample(ILogger logger)
    {
        _logger = logger;
    }

    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        // Log the request details
        _logger.LogInformation($"Request: {context.HttpContext.Request.Method} {context.HttpContext.Request.Path}");

        // Log the request body for POST requests
        if (context.HttpContext.Request.Method.Equals("POST", StringComparison.OrdinalIgnoreCase))
        {
            context.HttpContext.Request.EnableBuffering();

            // seek
            context.HttpContext.Request.Body.Seek(0, SeekOrigin.Begin);

            // Read the request body
            using var reader = new StreamReader(context.HttpContext.Request.Body, 
                encoding: Encoding.UTF8, detectEncodingFromByteOrderMarks: false, bufferSize: 8192,
                leaveOpen: true);

            var requestBody = await reader.ReadToEndAsync();

            // Reset the position of the request body stream
            context.HttpContext.Request.Body.Position = 0;

            _logger.LogInformation($"Request Body: {requestBody}");
        }

        // Call the action method
        var resultContext = await next();

        // Perform any post-action execution logic if needed
    }

inside program.cs在 program.cs 里面

ILogger logger = builder.Services.BuildServiceProvider().GetRequiredService<ILogger<Program>>();

builder.Services.AddControllersWithViews(config => 
{
    config.Filters.Add(new ActionFilterExample(logger));
});

在此处输入图像描述

Use the built in middleware that takes things like sensitive information in requests and performance into consideration (not buffering the entire request body into memory as a string to log).使用内置的中间件,考虑请求中的敏感信息和性能(不将整个请求主体缓冲到 memory 作为要记录的字符串)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM