在ASP.NET Core MVC中浏览器中止时HttpRequest未中止(取消) [英] HttpRequest not aborted (cancelled) on browser abort in ASP.NET Core MVC

查看:61
本文介绍了在ASP.NET Core MVC中浏览器中止时HttpRequest未中止(取消)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I wrote the following MVC Controller to test cancellation functionality:

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做到了,可以通过以下方式实现:

Say, I want to cancel the request, so the value 'true' is logged in the controller action above. This is possible server-side if the server implements the IHttpRequestLifetimeFeature. Luckily Kestrel does, and this can be accomplished the following way:

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

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

The problem however is that I want to cancel the request on the client side. For example, in the browser. In pre-core versions of ASP.NET MVC/WebApi the cancellation token would automatically be cancelled if the browser aborted a request. Example: refresh the page a couple of times in Chrome. In the Network tab of the chrome dev tools you can now see the previous (unfinished) request be cancelled.

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

The thing is: in ASP.NET Core running on Kestrel, I can only see the following entry in the log:

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

Microsoft.AspNetCore.Server.Kestrel.Internal.Networking.UvException: Error -4081 ECANCELED operation canceled

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

So the abort request from the browser DOES arrive and is handled by the Kestrel webserver. It does however not affect the RequestAborted property of the HttpContext in the controller, because the value 'false' is still logged by the method.

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

Question: Is there a way to abort/cancel my controller's method, so that the HttpContext.RequestAborted property will be marked as cancelled?

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

Perhaps I can make something that would subscribe to Kestrel's operation cancelled trigger and call the IHttpRequestLifetimeFeature.Abort() method?

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

Update: I did some further testing and it seems the HttpRequest IS in fact aborted, but there seems to be some kind of delay before the cancellation actually takes place. The delay is not time-factored, and seems to come straight from libuv (the library where the Kestrel webserver is build on top of). I posted more info on https://github.com/aspnet/KestrelHttpServer/issues/1103

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

More updates: Issue has been moved to another one, because the previous one contained multiple problems. https://github.com/aspnet/KestrelHttpServer/issues/1139

推荐答案

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

Turns out that that simply using HttpContext.RequestAborted is indeed the right way, but due to a bug in Kestrel (the order in which FIN/RST packages were handled), the request was not aborted on a browser abort.

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

The bug should finally be fixed in Kestrel 2.0.

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

See the updates in my question for more information.

这篇关于在ASP.NET Core MVC中浏览器中止时HttpRequest未中止(取消)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆