簡體   English   中英

記錄對多個端點的請求,而無需在 ASP.NET Core 中的每個端點中進行更改

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

我正在研究 Asp.Net Core API,大約有 1000 個端點可以有不同的主體(請求有效負載)。 我想記錄每個端點的傳入請求。 我不想 go 並在每個端點中進行更改。 那么有沒有辦法做到這一點?

我試過下面的。 但它將 requestBody 記錄為空字符串。 雖然我在 controller 操作方法中得到了請求 object 值。 以下代碼適用於 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
}

我已經嘗試過這個並且它適用於一個端點,但是可能有許多不同的請求類型所以我最終會使用多個 if else 並且我想避免它,基本上我正在尋找一個通用的解決方案。

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

注意:我讀過一些文章提到它可以使用中間件來完成,但在這個問題中我更感興趣的是修復我的代碼中的問題。 或者可以使用 ActionFilter 修復

首先,我強烈建議研究使用框架提供的現有 HTTP 日志記錄基礎設施,請注意,您可以使用UseWhen有條件地啟用它(就像在此處此處完成的一樣)。

如果由於某種原因它不適合您,那么針對您的問題:

但它將 requestBody 記錄為空字符串

這里有 2 個可能的問題(沒有設置來重現 ATM):

  1. EnableBuffering被調用得太晚了,嘗試在管道開始的某個地方添加下一個中間件(就像它在這里完成的那樣):
app.Use((context, next) =>
{
    context.Request.EnableBuffering();
    return next();
});
// ...
  1. 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}");
}

另請查看此答案

我測試了你的代碼,它似乎運行良好。 您是否將您的請求作為 JSON 與正文一起發送? 您能否驗證內容類型 header?

在此處輸入圖像描述

這是您的代碼,稍作修改。

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
    }

在 program.cs 里面

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

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

在此處輸入圖像描述

使用內置的中間件,考慮請求中的敏感信息和性能(不將整個請求主體緩沖到 memory 作為要記錄的字符串)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM