ASP.NET Core3.1 中間件middleware說明

 

中間件是一種裝配到應用管道以處理請求和響應的軟件。 每個組件:

  • 選擇是否將請求傳遞到管道中的下一個組件。
  • 可在管道中的下一個組件前後執行工作。

請求委託用於生成請求管道。 請求委託處理每個 HTTP 請求。

使用 RunMap 和 Use 擴展方法來配置請求委託。 可將一個單獨的請求委託並行指定爲匿名方法(稱爲並行中間件),或在可重用的類中對其進行定義。 這些可重用的類和並行匿名方法即爲中間件 ,也叫中間件組件 。 請求管道中的每個中間件組件負責調用管道中的下一個組件,或使管道短路。 當中間件短路時,它被稱爲“終端中間件” ,因爲它阻止中間件進一步處理請求。

將 HTTP 處理程序和模塊遷移到 ASP.NET Core 中間件介紹了 ASP.NET Core 和 ASP.NET 4.x 中請求管道之間的差異,並提供了更多的中間件示例。

使用 IApplicationBuilder 創建中間件管道

ASP.NET Core 請求管道包含一系列請求委託,依次調用。 下圖演示了這一概念。 沿黑色箭頭執行。

請求處理模式顯示請求到達、通過三個中間件進行處理以及響應離開應用。

每個委託均可在下一個委託前後執行操作。 應儘早在管道中調用異常處理委託,這樣它們就能捕獲在管道的後期階段發生的異常。

儘可能簡單的 ASP.NET Core 應用設置了處理所有請求的單個請求委託。 這種情況不包括實際請求管道。 調用單個匿名函數以響應每個 HTTP 請求。

 

public class Startup
{
    public void Configure(IApplicationBuilder app)
    {
        app.Run(async context =>
        {
            await context.Response.WriteAsync("Hello, World!");
        });
    }
}

 

用 Use 將多個請求委託鏈接在一起。 next 參數表示管道中的下一個委託。 可通過不 調用 next 參數使管道短路。 通常可在下一個委託前後執行操作,如以下示例所示:

 

public class Startup
{
    public void Configure(IApplicationBuilder app)
    {
        app.Use(async (context, next) =>
        {
            // Do work that doesn't write to the Response.
            await next.Invoke();
            // Do logging or other work that doesn't write to the Response.
        });
 
        app.Run(async context =>
        {
            await context.Response.WriteAsync("Hello from 2nd delegate.");
        });
    }
}

 

當委託不將請求傳遞給下一個委託時,它被稱爲“讓請求管道短路” 。 通常需要短路,因爲這樣可以避免不必要的工作。 例如,靜態文件中間件可以處理對靜態文件的請求,並讓管道的其餘部分短路,從而起到終端中間件 的作用。 如果中間件添加到管道中,且位於終止進一步處理的中間件前,它們仍處理 next.Invoke 語句後面的代碼。 不過,請參閱下面有關嘗試對已發送的響應執行寫入操作的警告。

警告

在向客戶端發送響應後,請勿調用 next.Invoke。 響應啓動後,針對 HttpResponse 的更改將引發異常。 例如,設置標頭和狀態代碼更改將引發異常。 調用 next 後寫入響應正文:

  • 可能導致違反協議。 例如,寫入的長度超過規定的 Content-Length
  • 可能損壞正文格式。 例如,向 CSS 文件中寫入 HTML 頁腳。

HasStarted 是一個有用的提示,指示是否已發送標頭或已寫入正文。

 

Run 委託不會收到 next 參數。 第一個 Run 委託始終爲終端,用於終止管道。 Run 是一種約定。 某些中間件組件可能會公開在管道末尾運行的 Run[Middleware] 方法:

 

public class Startup
{
    public void Configure(IApplicationBuilder app)
    {
        app.Use(async (context, next) =>
        {
            // Do work that doesn't write to the Response.
            await next.Invoke();
            // Do logging or other work that doesn't write to the Response.
        });
 
        app.Run(async context =>
        {
            await context.Response.WriteAsync("Hello from 2nd delegate.");
        });
    }
}

 

在前面的示例中,Run 委託將 "Hello from 2nd delegate." 寫入響應,然後終止管道。 如果在 Run 委託之後添加了另一個 Use 或 Run 委託,則不會調用該委託。

中間件順序

向 Startup.Configure 方法添加中間件組件的順序定義了針對請求調用這些組件的順序,以及響應的相反順序。 此順序對於安全性、性能和功能至關重要。

下面的 Startup.Configure 方法按照建議的順序增加與安全相關的中間件組件:

 

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseDatabaseErrorPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }
 
    app.UseHttpsRedirection();
    app.UseStaticFiles();
    // app.UseCookiePolicy();
 
    app.UseRouting();
    // app.UseRequestLocalization();
    // app.UseCors();
 
    app.UseAuthentication();
    app.UseAuthorization();
    // app.UseSession();
 
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Home}/{action=Index}/{id?}");
    });
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章