Asp.net-Core

在 ASP.NET Core MVC 中瀏覽器中止時,HttpRequest 未中止(取消)

  • June 20, 2017

我編寫了以下 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,這可能是伺服器端的。幸運的是,Kestrel 做到了,這可以通過以下方式完成:

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

然而問題是我想取消客戶端的請求。例如,在瀏覽器中。在 ASP.NET MVC/WebApi 的預核心版本中,如果瀏覽器中止請求,取消令牌將自動取消。範例:在 Chrome 中刷新頁面幾次。在 chrome 開發工具的 Network 選項卡中,您現在可以看到之前的(未完成的)請求被取消了。

問題是:在 Kestrel 上執行的 ASP.NET Core 中,我只能在日誌中看到以下條目:

Microsoft.AspNetCore.Server.Kestrel.Internal.Networking.UvException:錯誤 -4081 ECANCELED 操作已取消

因此,來自瀏覽器的中止請求確實到達並由 Kestrel 網路伺服器處理。但是,它不會影響控制器中 HttpContext 的 RequestAborted 屬性,因為該方法仍會記錄值“ false ”。

問題: 有沒有辦法中止/取消控制器的方法,以便將 HttpContext.RequestAborted 屬性標記為已取消?

也許我可以製作一些訂閱 Kestrel 的操作取消觸發器並呼叫 IHttpRequestLifetimeFeature.Abort() 方法的東西?

更新: 我做了一些進一步的測試,似乎 HttpRequest實際上已中止,但在取消實際發生之前似乎存在某種延遲。延遲不是時間因素,並且似乎直接來自 libuv(Kestrel 網路伺服器建立在其之上的庫)。我在https://github.com/aspnet/KestrelHttpServer/issues/1103上發布了更多資訊

更多更新: 問題已移至另一個問題,因為前一個問題包含多個問題。https://github.com/aspnet/KestrelHttpServer/issues/1139

事實證明,簡單地使用 HttpContext.RequestAborted 確實是正確的方法,但由於 Kestrel 中的一個錯誤(處理 FIN/RST 包的順序),請求沒有在瀏覽器中止時中止。

該錯誤最終應該在 Kestrel 2.0 中得到修復。

有關更多資訊,請參閱我的問題中的更新。

引用自:https://stackoverflow.com/questions/39574061