我可以安全地捕获并忽略 BadHttpRequestException:请求内容意外结束。在 ASP.NET Core 中

问题描述 投票:0回答:1

我们有一个流量很大的网站。特别是在高峰时段,当人们快速浏览大量页面时,我们的日志中会出现如下所示的异常:

Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException: Unexpected end of request content.
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Http1ContentLengthMessageBody.ReadAsyncInternal(CancellationToken cancellationToken)
   at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpRequestStream.ReadAsyncInternal(Memory`1 destination, CancellationToken cancellationToken)
   at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
   at Microsoft.AspNetCore.WebUtilities.FileBufferingReadStream.ReadAsync(Memory`1 buffer, CancellationToken cancellationToken)
   at System.IO.StreamReader.ReadBufferAsync(CancellationToken cancellationToken)
   at System.IO.StreamReader.ReadAsyncInternal(Memory`1 buffer, CancellationToken cancellationToken)
   at Newtonsoft.Json.JsonTextReader.ReadDataAsync(Boolean append, Int32 charsRequired, CancellationToken cancellationToken)
   at Newtonsoft.Json.JsonTextReader.ParseValueAsync(CancellationToken cancellationToken)
   [...]

我不想关注代码本身,因为它无关紧要。

在 ValueProviding for ASP.NET 期间有类似的事情:

var stream_reader = new StreamReader(context.ActionContext.HttpContext.Request.Body);

var json_reader = new JsonTextReader(stream_reader);

bool success = await json_reader.ReadAsync();

我从未能够在我的调试环境中复制这些错误。我有一种感觉,当用户更改页面时发生 XHR 请求时,就会发生这种情况。

一些浏览器只是停止整个请求,因此他们不再发送他们承诺的有效负载。

这些只是假设。我真的很难找到任何相关信息。

我找到了this帖子,但其中有很多零散的意见。

有些人正在等待 ASP.NET 的错误修复,但与此同时,这完全让我的日志充满了错误。

我可以安全地捕获此处的

BadHttpRequestException
异常并忽略它们吗?或者我可能会错过关键错误吗?有没有这方面的决定性信息?

asp.net-core exception request
1个回答
0
投票

我可以在这里安全地捕获 BadHttpRequestException 异常吗? 别理他们?或者我可能会错过关键错误吗?有没有 有什么决定性的信息吗?

根据您共享的代码片段和描述,我尝试重现您的问题。然而,正如您也提到的,它是间歇性发生的,在我这边也很难重现这个问题。

因为,这可能会因为很多原因而变得混乱。例如,缺少请求正文部分、格式错误或太大,它会抛出 BadHttpRequestException。发生这种情况的原因通常是网络问题、用户取消、内容类型错误、标头丢失或请求方法不正确。

因此,为了解决这个问题,很难为您提供任何直接的解决方案,相反,您可以继续记录通常发生的错误,尝试检查应用程序日志、事件查看器日志。

如果这个异常肯定会阻塞您的应用程序,您可以捕获错误并记录,最后忽略或抛出响应,这样就不会限制方法执行。

您可以执行以下操作:

public class BadReqeustHandlerController : ControllerBase
{
    private readonly ILogger<BadReqeustHandlerController> _logger;

    public BadReqeustHandlerController(ILogger<BadReqeustHandlerController> logger)
    {
        _logger = logger;
    }

    [HttpPost]
    [Route("BadRequestBodyHandlerMethod")]
    public async Task<IActionResult> BadRequestBodyHandlerMethod()
    {
        try
        {
           
            string requestBody;
            using (var reader = new StreamReader(HttpContext.Request.Body))
            {
                requestBody = await reader.ReadToEndAsync();
            }

            var data = JsonConvert.DeserializeObject<Dictionary<string, string>>(requestBody);
            return Ok(data);
        }
        catch (BadHttpRequestException ex) when (ex.Message.Contains("Unexpected end of request content"))
        {
            _logger.LogWarning("BadHttpRequestException: Unexpected end of request content - {Message}", ex.Message);

            // Ignore this exception, as it's likely due to client disconnection
            return StatusCode(StatusCodes.Status400BadRequest, "Client disconnected before the request could be completed.");
        }
        catch (JsonException ex)
        {
            _logger.LogWarning("JSON exception occurred: {Message}", ex.Message);
            return StatusCode(StatusCodes.Status400BadRequest, "Malformed JSON request.");
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "An unexpected error occurred");
            return StatusCode(StatusCodes.Status500InternalServerError, "An unexpected error occurred.");
        }
    }
}

注意: 正如您所看到的,当没有错误或异常时,该方法将毫无问题地执行。但是,虽然会立即出现任何问题

BadHttpRequestException
JsonException
,但它会立即记录错误并返回响应,而不会阻止操作。

输出:

enter image description here

注意: 请记住,这不是我之前告诉您的确切解决方案。除了上述 catch 中的异常处理程序之外,您还可以考虑使用 asp.net core 中间件 来处理任何类型的间歇性问题。

© www.soinside.com 2019 - 2024. All rights reserved.