在ASP.NET Core MVC中浏览器中止时HttpRequest未中止(取消)

尼克·穆勒(Nick Muller)

我编写了以下MVC Controller来测试取消功能:

class MyController : Controller
{
    [HttpGet("api/CancelTest")]
    async Task<IActionResult> Get()
    {
        await Task.Delay(1000);
        CancellationToken token = HttpContext.RequestAborted;
        bool cancelled = token.IsCancellationRequested;
        logger.LogDebug(cancelled.ToString());
        return Ok();
    }
}

说,我想取消请求,因此在上面的控制器操作中记录了值' true '。如果服务器实现IHttpRequestLifetimeFeature,则这可能在服务器端。幸运的是,Kestrel做到了,可以通过以下方式实现:

var feature = (IHttpRequestLifetimeFeature) HttpContext.Features[typeof(IHttpRequestLifetimeFeature)];
feature.Abort();

但是问题是我想在客户端取消请求。例如,在浏览器中。在ASP.NET MVC / WebApi的预核心版本中,如果浏览器中止请求,则取消令牌将自动被取消。示例:在Chrome中刷新页面两次。现在,在chrome开发工具的“网络”标签中,您可以看到之前(未完成)的请求已被取消。

事实是:在Kestrel上运行的ASP.NET Core中,我只能在日志中看到以下条目:

Microsoft.AspNetCore.Server.Kestrel.Internal.Networking.UvException:错误-4081 ECANCELED操作被取消

因此,来自浏览器的中止请求确实到达并由Kestrel Web服务器处理。但是,它不会影响控制器中HttpContext的RequestAborted属性,因为该方法仍会记录值' false '。

问题:有没有办法中止/取消控制器的方法,以便将HttpContext.RequestAborted属性标记为已取消?

也许我可以做出一些可以订阅Kestrel操作取消的触发器并调用IHttpRequestLifetimeFeature.Abort()方法的东西?

更新:我做了一些进一步的测试,看来HttpRequest IS实际上已经中止了,但是在实际取消之前似乎存在某种延迟。延迟不是时间因素,它似乎直接来自libuv(在其上构建Kestrel Web服务器的库)。我在https://github.com/aspnet/KestrelHttpServer/issues/1103上发布了更多信息

更多更新:问题已移至另一问题,因为前一个问题包含多个问题。https://github.com/aspnet/KestrelHttpServer/issues/1139

尼克·穆勒(Nick Muller)

事实证明,仅使用HttpContext.RequestAborted确实是正确的方法,但是由于Kestrel中的错误(处理FIN / RST包的顺序),该请求并未因浏览器中止而中止。

该错误最终应在Kestrel 2.0中修复。

有关更多信息,请参阅我的问题中的更新。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章