使用 ASP.NET Core Kestrel Web 伺服器要求清空

開啟 HTTP 連線相當耗時。 針對 HTTPS,它也需要大量資源。 因此,Kestrel 會嘗試根據 HTTP/1.1 通訊協定重複使用連線。 要求本文必須完全取用,才能重複使用連線。 應用程式不一定會取用要求本文,例如伺服器傳回重新導向或 404 回應的 HTTP POST 要求。 在 HTTP POST 重新導向案例中:

  • 用戶端可能已經傳送部分的 POST 資料。
  • 伺服器會寫入 301 回應。
  • 在完整讀取先前要求本文的 POST 資料之前,連線無法用於新的要求。
  • Kestrel 會嘗試清空要求本文。 清空要求本文表示在不處理資料的情況下讀取和捨棄資料。

清空流程會衡量允許重複使用連線的必要性與清空剩餘資料所需的時間,並在兩者之間做出取捨:

  • 清空有五秒的逾時限制,您無法設定這個時間。
  • 如果在逾時之前尚未讀取 Content-LengthTransfer-Encoding 標頭指定的所有資料,連線就會關閉。

有時,您可能希望在寫入回應之前或之後立即終止要求。 例如,用戶端可能有限制資料的上限。 限制上傳的資料可能列為優先。 在這種情況下,若要終止要求,請從控制器、Razor Page 或中介軟體中呼叫 HttpCoNtext.Abort

呼叫 Abort 有一些注意事項:

  • 建立新連線可能既緩慢又很昂貴。
  • 無法保證用戶端在連線關閉之前已讀取回應。
  • 呼叫 Abort 的情況應該很少見,並且保留用於嚴重的錯誤案例,而不是常見的錯誤。
    • 只有在需要解決特定問題時,才呼叫 Abort。 例如,如果惡意用戶端嘗試存取 POST 資料,或用戶端程式碼中存在造成大規模或大量要求的錯誤,則呼叫 Abort
    • 請不要因為常見的錯誤情況而呼叫 Abort,例如 HTTP 404 (找不到)。

呼叫 Abort 之前呼叫 HttpResponse.CompleteAsync,可確保伺服器已完成寫入回應。 不過,用戶端行為是無法預測的,它們在連線中止之前可能並未讀取回應。

此流程與 HTTP/2 不同,因為該通訊協定支援在不關閉連線的情況下中止個別要求串流。 五秒清空逾時並不適用。 如果在完成回應之後有任何未讀取的要求本文資料,則伺服器會傳送 HTTP/2 RST 框架。 系統會忽略其他要求本文資料框架。

可能的話,用戶端最好使用 Expect:100-continue 要求標頭並等待伺服器回應,然後再開始傳送要求本文。 這使得用戶端有機會檢查回應,並在傳送不需要的資料之前中止。