原文链接:http://www.cnblogs.com/RainingNight/p/middleware-in-asp-net-core.html
中间件处理请求主要分为三个阶段:
1. 中间件的注册
2. 中间件的构建,形成请求处理管道
3. 请求流入管道,中间件依次执行。
对于中间件的注册,就是简单的将中间件按顺序添加到IApplicationBuilder维护的中间件集合中;
对于中间件的构建,主要是为了完成中间件之间的衔接,它的衔接设计的很巧妙,通过反转中间件集合并引入404中间件来完成的,从而确保了最终形成的请求管道也就是按照我们注册中间件的顺序来处理请求,即Middleware 1-->Middleware 2-->...--> 404
IApplicationBuilder 是用来构建请求管道的,而所谓请求管道,本质上就是对 HttpContext 的一系列操作,即通过对 Request 的处理,来生成 Reponse。因此,在 ASP.NET Core 中定义了一个 RequestDelegate 委托,来表示请求管道中的一个步骤
而对请求管道的注册是通过 Func<RequestDelegate, RequestDelegate>
类型的委托(也就是中间件)来实现的。
为什么要设计一个这样的委托呢?让我们来分析一下,它接收一个 RequestDelegate 类型的参数,并返回一个 RequestDelegate 类型,也就是说前一个中间件的输出会成为下一个中间件的输入,这样把他们串联起来,形成了一个完整的管道
Use
是我们非常熟悉的注册中间件的方法,其实现非常简单,就是将注册的中间件保存到其内部属性 _components
中
public IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware) { _components.Add(middleware); return this; }
我们使用Use注册两个简单的中间件:
public void Configure(IApplicationBuilder app) { app.Use(next => { Console.WriteLine("A"); return async (context) => { // 1. 对Request做一些处理 // TODO // 2. 调用下一个中间件 Console.WriteLine("A-BeginNext"); await next(context); Console.WriteLine("A-EndNext"); // 3. 生成 Response //TODO }; }); app.Use(next => { Console.WriteLine("B"); return async (context) => { // 1. 对Request做一些处理 // TODO // 2. 调用下一个中间件 Console.WriteLine("B-BeginNext"); await next(context); Console.WriteLine("B-EndNext"); // 3. 生成 Response //TODO }; }); }
如上,注册了A和B两个中间件,通常每一个中间件有如上所示三个处理步骤,也就是围绕着Next
分别对Request和Respone做出相应的处理,而B的执行会嵌套在A的里面,因此A是第一个处理Request,并且最后一个收到Respone,这样就构成一个经典的的U型管道。
在 Hosting 的启动中,便是通过该 Build
方法创建一个 RequestDelegate 类型的委托,Http Server 通过该委托来完成整个请求的响应