asp .net core 中間件
- 2020 年 8 月 29 日
- 筆記
- .net core(web)
前言
對中間件的一個概況,在《重新整理.net core 計1400篇》系列後面會深入。
正文
什麼是中間件呢?
其實中間件這個概念來源於分佈式,當然這是一個狹隘的概念了,現在中間件概念就非常廣泛了。
官網給出了這樣一張圖,這張圖認為從請求到響應過程中間都是中間件,包括我們認為的路由。
看一段node代碼:
var http = require("http");
http.createServer(function(req,res){
res.writeHead(200,{"Content-type":"text/blain"});
res.write("Hello NodeJs");
res.end();
}).listen(8888);
沒有學過node 也是ok的,從字面意思就是創建了一個http服務,然後端口是80。
createServer 可以傳入一個方法,中間有兩個參數,一個參數是req,另一個參數就是res。
其實就是這麼回事,我們寫的就是這個這個方法裏面的代碼,至於,你想拿到req的什麼參數,或者給res寫入什麼信息,這些都是中間件的範疇。
那麼問題來了,問什麼叫做中間件呢?從語文的層面上理解,那就是分開的,一件一件的。
把這件要執行的這些封裝成一個一個模塊,那麼這些模塊,這些可以通過調用next執行下一個模塊,同樣,如果不調用,那麼中間件模塊就會中斷,因為有時候真的需要中斷,比如說權限中間件,
檢查到權限不符合直接返回讓其跳轉到權限頁面,剩下的模塊也用不到。
用 Use 將多個請求委託鏈接在一起。 next 參數表示管道中的下一個委託。 可通過不調用 next 參數使管道短路。
當委託不將請求傳遞給下一個委託時,它被稱為「讓請求管道短路」。 通常需要短路,因為這樣可以避免不必要的工作。
下圖為asp .net core 中默認的中間件順序,當然可以自己修改,但是這是一種推薦做法。
挺合理的一個東西,一開始就填入了異常處理機制。
然後是強制https 轉換->重定向->靜態資源文件->路由->是否跨域->認證->授權->我們自己自定義需求的。
因為這個endpoint 是不建議我們修改的,當然我們可以修改源碼中,畢竟開源了,but not must。
官網中同樣給了我們這個endpoint 做了什麼,其實就是官方自己封裝了一些中間件。
當然我們也可以進行對endpoint自我的調整,因為可能使用不同的模板引擎:
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
從上面得到一個推薦的中間件註冊來看,認證和授權在靜態文件之後,那麼我們知道我們的資源時需要授權來保護的。
那麼如何保護靜態資源呢?這後面會有專門的一章實踐一下,看下是什麼原理。
好的,那麼看一下我們如何自定義中間件吧,也就是實踐一下下面這種圖。
Middleware1
public class Middleware1
{
public readonly RequestDelegate _next;
public Middleware1(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
Console.WriteLine("Middleware1");
await _next(context);
await context.Response.WriteAsync("Middleware1");
}
}
public class Middleware2
{
public readonly RequestDelegate _next;
public Middleware2(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
Console.WriteLine("Middleware2");
await _next(context);
await context.Response.WriteAsync("Middleware2");
}
}
Middleware3
public class Middleware3
{
public readonly RequestDelegate _next;
public Middleware3(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
Console.WriteLine("Middleware3");
await _next(context);
await context.Response.WriteAsync("Middleware3");
}
}
擴展方法:
public static class Middleware1MiddlewareExtensions
{
public static IApplicationBuilder UserMiddleware1(this IApplicationBuilder builder)
{
return builder.UseMiddleware<Middleware1>();
}
public static IApplicationBuilder UserMiddleware2(this IApplicationBuilder builder)
{
return builder.UseMiddleware<Middleware2>();
}
public static IApplicationBuilder UserMiddleware3(this IApplicationBuilder builder)
{
return builder.UseMiddleware<Middleware3>();
}
}
加入中間件隊列:
app.UserMiddleware1();
app.UserMiddleware2();
app.UserMiddleware3();
request 順序
response 順序
這其實就是一種職責鏈模式,每個中間件確定是否該需求是否要下一級處理,同樣會產生一個處理回調。