asp.net core 系列之中間件基礎篇(middleware)

 

中間件是一種插入到管道上進行處理請求和響應的軟件;每一箇中間件組件具備下面的功能:session

  1. 選擇是否把請求傳遞到管道上的下一個組件
  2. 能夠在下一個組件的以前和以後作處理工做

 

請求委託(request delegate)是用於創建(build)請求管道的,請求委託能夠處理每一個Http的請求;app

請求委託被配置的方法有三種:Run、Map、Use 擴展方法;async

 

用 IApplicationBuilder 建立中間件管道

請求管道由一系列請求委託組成,一個調用一個;以下圖函數

每一個委託均可以在下一個委託以前和以後執行。異常處理的委託在管道中被儘早調用,由於它能夠捕獲到後面管道中發生的錯誤。ui

 

單個的請求委託可使用 run

使用一個匿名函數處理每一個 Http 請求;而且使用的是 run ,它表示管道的結束,即最後一箇中間件,不會再傳遞到下一個中間件spa

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

 

鏈式的多個請求委託在一塊兒,使用 use

next 參數 表明管道中的下一個委託,能夠在下一個委託以前和以後進行處理;你也能夠不調用 next 參數,直接短路管道(即不會傳遞到下一個委託/中間件)。code

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.");
        });
    }
}

 

順序

這裏的順序是指中間件被加到 Startup.Configure 方法的順序決定了中間件順序處理請求和逆序處理響應。因此,添加順序是很重要的orm

 

通常的應用中的 Startup.Configure 方法添加中間組件的順序:server

  1. Exception/error handling
  2. HTTP Strict Transport Security Protocol
  3. HTTPS redirection
  4. Static file server
  5. Cookie policy enforcement
  6. Authentication
  7. Session
  8. MVC
public void Configure(IApplicationBuilder app)
{
    if (env.IsDevelopment())
    {
        // When the app runs in the Development environment:
        //   Use the Developer Exception Page to report app runtime errors.
        //   Use the Database Error Page to report database runtime errors.
     // 添加異常中間件以後,後面中間件發生的異常都會被捕獲
app.UseDeveloperExceptionPage(); app.UseDatabaseErrorPage(); } else { // When the app doesn't run in the Development environment: // Enable the Exception Handler Middleware to catch exceptions // thrown in the following middlewares. // Use the HTTP Strict Transport Security Protocol (HSTS) // Middleware. app.UseExceptionHandler("/Error"); app.UseHsts(); } // Use HTTPS Redirection Middleware to redirect HTTP requests to HTTPS.使用https重定向中間件來重定向http請求到https請求 app.UseHttpsRedirection(); // Return static files and end the pipeline. app.UseStaticFiles(); // Use Cookie Policy Middleware to conform to EU General Data // Protection Regulation (GDPR) regulations. app.UseCookiePolicy(); // Authenticate before the user accesses secure resources. app.UseAuthentication(); // If the app uses session state, call Session Middleware after Cookie // Policy Middleware and before MVC Middleware. app.UseSession(); // Add MVC to the request pipeline. app.UseMvc(); }

 

Use , Run 和 Map 的用法

使用 Use , Run 和 Map 配置 HTTP 管道。中間件

 

Use 方法若是不調用next 就會形成短路;

 

一些中間件組件可能會暴露 Run [ Middleware ] 方法 在管道的結束處運行;

 

Map 擴展 主要用做一種分支管道的慣例:

  Map* 根據這給出的請求路徑是否匹配來進入管道。

public class Startup
{
    private static void HandleMapTest1(IApplicationBuilder app)
    {
        app.Run(async context =>
        {
            await context.Response.WriteAsync("Map Test 1");
        });
    }

    private static void HandleMapTest2(IApplicationBuilder app)
    {
        app.Run(async context =>
        {
            await context.Response.WriteAsync("Map Test 2");
        });
    }

    public void Configure(IApplicationBuilder app)
    {
        app.Map("/map1", HandleMapTest1);

        app.Map("/map2", HandleMapTest2);

        app.Run(async context =>
        {
            await context.Response.WriteAsync("Hello from non-Map delegate. <p>");
        });
    }
}

 

若是路徑匹配 /map1 ,則執行 HandleMapTest1;

若是路徑匹配 /map2 , 則執行 HandleMapTest2 ;

以下示例:

 

MapWhen 的用法

當知足某個條件時,執行

public class Startup
{
    private static void HandleBranch(IApplicationBuilder app)
    {
        app.Run(async context =>
        {
            var branchVer = context.Request.Query["branch"];
            await context.Response.WriteAsync($"Branch used = {branchVer}");
        });
    }

    public void Configure(IApplicationBuilder app)
    {
        app.MapWhen(context => context.Request.Query.ContainsKey("branch"),
                               HandleBranch);

        app.Run(async context =>
        {
            await context.Response.WriteAsync("Hello from non-Map delegate. <p>");
        });
    }
}

 

示例以下:

 

 

 另外,map支持嵌套

app.Map("/level1", level1App => {
    level1App.Map("/level2a", level2AApp => {
        // "/level1/level2a" processing
    });
    level1App.Map("/level2b", level2BApp => {
        // "/level1/level2b" processing
    });
});

並且,map支持每次匹配多個段

public class Startup
{
    private static void HandleMultiSeg(IApplicationBuilder app)
    {
        app.Run(async context =>
        {
            await context.Response.WriteAsync("Map multiple segments.");
        });
    }

    public void Configure(IApplicationBuilder app)
    {
        app.Map("/map1/seg1", HandleMultiSeg);  //此句示例

        app.Run(async context =>
        {
            await context.Response.WriteAsync("Hello from non-Map delegate.");
        });
    }
}

 

 另外還有不少內置的中間件可供使用,可根據須要進行使用

 

參考網址:

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/middleware/?view=aspnetcore-2.2

相關文章
相關標籤/搜索