淺析asp .net core 中間件
https://www.cnblogs.com/aoximin/p/13576479.html
夢里小探花
前言
對(duì)中間件的一個(gè)概況,在《重新整理.net core 計(jì)1400篇》系列后面會(huì)深入。
正文
什么是中間件呢?
其實(shí)中間件這個(gè)概念來源于分布式,當(dāng)然這是一個(gè)狹隘的概念了,現(xiàn)在中間件概念就非常廣泛了。

官網(wǎng)給出了這樣一張圖,這張圖認(rèn)為從請(qǐng)求到響應(yīng)過程中間都是中間件,包括我們認(rèn)為的路由。
看一段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);
沒有學(xué)過node 也是ok的,從字面意思就是創(chuàng)建了一個(gè)http服務(wù),然后端口是8888。
createServer 可以傳入一個(gè)方法,中間有兩個(gè)參數(shù),一個(gè)參數(shù)是req,另一個(gè)參數(shù)就是res。
其實(shí)就是這么回事,我們寫的就是這個(gè)這個(gè)方法里面的代碼,至于,你想拿到req的什么參數(shù),或者給res寫入什么信息,這些都是中間件的范疇。
那么問題來了,問什么叫做中間件呢?從語文的層面上理解,那就是分開的,一件一件的。
把這件要執(zhí)行的這些封裝成一個(gè)一個(gè)模塊,那么這些模塊,這些可以通過調(diào)用next執(zhí)行下一個(gè)模塊,同樣,如果不調(diào)用,那么中間件模塊就會(huì)中斷,因?yàn)橛袝r(shí)候真的需要中斷,比如說權(quán)限中間件,
檢查到權(quán)限不符合直接返回讓其跳轉(zhuǎn)到權(quán)限頁面,剩下的模塊也用不到。
用 Use 將多個(gè)請(qǐng)求委托鏈接在一起。next 參數(shù)表示管道中的下一個(gè)委托。可通過不調(diào)用 next 參數(shù)使管道短路。
當(dāng)委托不將請(qǐng)求傳遞給下一個(gè)委托時(shí),它被稱為“讓請(qǐng)求管道短路”。通常需要短路,因?yàn)檫@樣可以避免不必要的工作。
下圖為asp .net core 中默認(rèn)的中間件順序,當(dāng)然可以自己修改,但是這是一種推薦做法。

挺合理的一個(gè)東西,一開始就填入了異常處理機(jī)制。
然后是強(qiáng)制https 轉(zhuǎn)換->重定向->靜態(tài)資源文件->路由->是否跨域->認(rèn)證->授權(quán)->我們自己自定義需求的。
因?yàn)檫@個(gè)endpoint 是不建議我們修改的,當(dāng)然我們可以修改源碼中,畢竟開源了,but not must。
官網(wǎng)中同樣給了我們這個(gè)endpoint 做了什么,其實(shí)就是官方自己封裝了一些中間件。

當(dāng)然我們也可以進(jìn)行對(duì)endpoint自我的調(diào)整,因?yàn)榭赡苁褂貌煌哪0逡?
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
從上面得到一個(gè)推薦的中間件注冊(cè)來看,認(rèn)證和授權(quán)在靜態(tài)文件之后,那么我們知道我們的資源時(shí)需要授權(quán)來保護(hù)的。
那么如何保護(hù)靜態(tài)資源呢?這后面會(huì)有專門的一章實(shí)踐一下,看下是什么原理。
好的,那么看一下我們?nèi)绾巫远x中間件吧,也就是實(shí)踐一下下面這種圖。

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");
}
}
擴(kuò)展方法:
public static class Middleware1MiddlewareExtensions
{
public static IApplicationBuilder UserMiddleware1(this IApplicationBuilder builder)
{
return builder.UseMiddleware();
}
public static IApplicationBuilder UserMiddleware2(this IApplicationBuilder builder)
{
return builder.UseMiddleware();
}
public static IApplicationBuilder UserMiddleware3(this IApplicationBuilder builder)
{
return builder.UseMiddleware();
}
}
加入中間件隊(duì)列:
app.UserMiddleware1();
app.UserMiddleware2();
app.UserMiddleware3();
request 順序
response 順序
這其實(shí)就是一種職責(zé)鏈模式,每個(gè)中間件確定是否該需求是否要下一級(jí)處理,同樣會(huì)產(chǎn)生一個(gè)處理回調(diào)。
