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

查看:18
本文介绍了在 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 开发工具的 Network 标签中,您现在可以看到之前的(未完成的)请求被取消了.

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 网络服务器处理.但它不会影响控制器中 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 网络服务器建立在其之上的库).我在 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天全站免登陆