在浏览器中止时,HttpRequest没有中止(取消).. NET Core MVC



我编写了以下MVC控制器来测试取消功能:

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,这在服务器端是可能的。幸运的是,红隼做到了,这可以通过以下方式完成:

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

问题是我想在客户端取消请求。例如,在浏览器中。在pre-core版本的ASP。如果浏览器终止请求,取消令牌将自动取消。示例:在Chrome中刷新页面几次。在chrome开发工具的网络选项卡中,您现在可以看到先前(未完成)的请求被取消。

问题是:在ASP中。. NET Core在Kestrel上运行时,我只能在日志中看到以下条目:

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

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

问题:是否有一种方法来中止/取消我的控制器的方法,以便HttpContext。请求建立的属性将被标记为已取消?

也许我可以做一些东西,将订阅红隼的操作取消触发器和调用IHttpRequestLifetimeFeature.Abort()方法?

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

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

事实证明,只需使用HttpContext。requestablished确实是正确的方式,但是由于Kestrel中的一个bug(处理FIN/RST包的顺序),请求在浏览器abort时没有被中止。

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

请参阅我的问题中的更新以获取更多信息。

最新更新