我有一个ASP.NET Core Web应用程序,它接受来自经过身份验证的用户的文件上传,以及一些错误处理,以便在发生异常时通知我(Exceptional)。我的问题是,由于用户通过移动设备在覆盖范围不可靠的区域访问应用程序,我会定期收到BadHttpRequestException
的警报。我过去常常使用2.0,但是直到2.1中的异常描述更新,我才知道它与MinRequestBodyDataRate
特别相关,或者它是可配置的。
我已经使用以下
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseKestrel(options =>
{
options.Limits.MinRequestBodyDataRate = new MinDataRate(240.0, TimeSpan.FromSeconds(10.0));
})
.UseStartup<Startup>();
这会使等待客户端/浏览器的持续时间加倍,但我仍然会收到错误警报。我无法控制用户的不良接收,但我仍然希望尝试找到一种方法来缓解错误。我可以进一步扩展最小值,但如果可能的话,我不想为整个应用程序执行此操作。理想情况下,它是处理上传的特定路线/操作。我能够找到的文档表明可以使用IHttpMinRequestBodyDataRateFeature
配置此最小值。我想过把它放在动作中,但我不认为动作甚至被调用,直到modelbinding上传整个文件才能将它绑定到我的参数。
public async Task<IActionResult> Upload(IFormFile file)
{
var minRequestBodyDataRateFeature = HttpContext.Features.Get<IHttpMinRequestBodyDataRateFeature>();
minRequestBodyDataRateFeature.MinDataRate = new MinDataRate(240, TimeSpan.FromSeconds(30));
myDocumentService.SaveFile(file);
}
这在某种程度上得到了缓解,因为我之前已经实现了分块上传,并且只在最后一个块出现时将文件保存到服务/数据库(在中间的临时位置逐渐构建文件)。但即使通过BadHttpRequestException
延长了持续时间,我仍然可以得到这些CreateWebHostBuilder
(因为它没有相关性,所以没有显示分块)。
我认为最好的选择可能是尝试在设置中间件的配置方法中连接它,但我不确定仅将其应用于一个操作的最佳方法。可能是网址?而且我想知道如果我通过将最低费率设置为null
来完全禁用最低费率会有什么影响。
我基本上只是希望连接能够更好地容忍质量差的连接,同时不会为应用程序的其他方面造成太多的烦恼。
Startup.Configure()
中),这样它只适用于受影响的路由/网址/操作。答案 0 :(得分:1)
我注意到了同样的问题。我有更大的文件,用户可以从我的网站下载,有些人,根据地区,下载速度慢,下载停止一段时间后。我也在日志中看到例外。
我不建议禁用该功能,因为一些卡住或非常慢的连接,可能总结。只需增加时间并将速率降低到可以说您的网页仍然可用的值。
对于特定的网址,我不这样做。除非您注意到某些性能问题,否则页面具有相同设置时不会受到影响。
另请注意,还有MinResponseDataRate
选项。
最好的方法是在应用程序启动时为所有路由设置一些合理的值。日志中总会出现例外情况,因为人们失去了与互联网的连接,而且需要在一段时间后关闭连接才能释放资源。
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseKestrel(options =>
{
options.Limits.MinRequestBodyDataRate =
new MinDataRate(bytesPerSecond: 80, gracePeriod: TimeSpan.FromSeconds(20));
options.Limits.MinResponseDataRate =
new MinDataRate(bytesPerSecond: 80, gracePeriod: TimeSpan.FromSeconds(20));
})
.ConfigureLogging((hostingContext, logging) =>
{
logging.ClearProviders();
logging.SetMinimumLevel(LogLevel.Trace);
})
.UseNLog()
.UseStartup<Startup>()
.Build();
}
请同时查看您的异步上传方法。确保您有等待或返回任务。我不认为它以这种方式编译。
答案 1 :(得分:0)
这是您可以使用在模型绑定之前运行的ResourceFilter进行的选择。
using System;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.AspNetCore.Server.Kestrel.Core.Features;
using Microsoft.Extensions.DependencyInjection;
namespace YourNameSpace
{
public class RateFilter : Attribute, IResourceFilter
{
private const string EndPoint = "YourEndPoint";
public void OnResourceExecuting(ResourceExecutingContext context)
{
try
{
if (!context.HttpContext.Request.Path.Value.Contains(EndPoint))
{
throw new Exception($"This filter is intended to be used only on a specific end point '{EndPoint}' while it's being called from '{context.HttpContext.Request.Path.Value}'");
}
var minRequestRateFeature = context.HttpContext.Features.Get<IHttpMinRequestBodyDataRateFeature>();
var minResponseRateFeature = context.HttpContext.Features.Get<IHttpMinResponseDataRateFeature>();
//Default Bytes/s = 240, Default TimeOut = 5s
if (minRequestRateFeature != null)
{
minRequestRateFeature.MinDataRate = new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
}
if (minResponseRateFeature != null)
{
minResponseRateFeature.MinDataRate = new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
}
}
catch (Exception ex)
{
//Log or Throw
}
}
public void OnResourceExecuted(ResourceExecutedContext context)
{
}
}
}
然后您可以在特定端点上使用属性,例如
[RateFilter]
[HttpPost]
public IActionResult YourEndPoint(YourModel request)
{
return Ok();
}
return
代替throw