中间件 Middleware
大约 4 分钟
中间件 Middleware
概念
间件是一种装配到应用管道以处理请求和响应的软件
- 选择是否将请求传递到管道中的下一个组件。
- 可在管道中的下一个组件前后执行工作。
中间件由前逻辑、next、后逻辑3部分组成,前逻辑为第一段要执行的逻辑代码、next为指向下一个中间件的调用、后逻辑为从下一个中间件执行返回所执行的逻辑代码。
中间件原理图
ASP.NET Core MVC 管道中间件图
终结点中间件调用图
中间件的三个概念
Map :用来定义处理管道与请求路由的映射
**Use ** :将多个请求委托链接在一起
Run :单个请求委托,没有
next
参数,用于终止管道一个 Map 中包含多个 Use 和一个 Run
当委托不将请求传递给下一个委托时,它被称为“让请求管道短路”
添加中间件不一定需要使用 Map,可以直接使用
appbuilder.Use()
app.Map("/test", async appbuilder => { appbuilder.Use(async (context, next) => { context.Response.ContentType = "text/html"; await context.Response.WriteAsync("1 Start<br/>"); await next.Invoke(); await context.Response.WriteAsync("1 End<br/>"); }); appbuilder.Use(async (context, next) => { await context.Response.WriteAsync("2 Start<br/>"); await next.Invoke(); await context.Response.WriteAsync("2 End<br/>"); }); appbuilder.Run(async ctx => { await ctx.Response.WriteAsync("hello middleware <br/>"); }); });
中间件类
中间件类是一个普通的.NET类,它不需要继承任何父类或者实现任何接口,类名一般以 Middleware 结尾
需要有一个构造方法,构造方法至少要有一个RequestDelegate类型的参数,这个参数用来指向下一个中间件
需要定义一个名字为Invoke或InvokeAsync的方法,方法至少有一个HttpContext类型的参数,方法的返回值必须是Task类型
public class 自定义中间件类名 { private readonly RequestDelegate _next; public RequestSetOptionsMiddleware(RequestDelegate next) { _next = next; } public async Task Invoke(HttpContext httpContext) { /* code */ await _next(httpContext); } }
引用中间件类 :
UseMiddleware
app.Map("/test", async appbuilder => { appbuilder.UseMiddleware<【自定义中间件类名】>(); appbuilder.Run(async ctx => {/*其他代码*/}); });
常见应用场景中间件
- 异常/错误处理
- 当应用在开发环境中运行时:
- UseDeveloperExceptionPage :报告应用运行时错误
- UseDatabaseErrorPage :报告数据库运行时错误
- 当应用在生产环境中运行时:
- UseExceptionHandler :捕获以下中间件中引发的异常
- UseHsts :HTTP 严格传输安全协议 (HSTS) 中间件,添加
Strict-Transport-Security
标头。
- 当应用在开发环境中运行时:
- UseHttpsRedirection :将 HTTP 请求重定向到 HTTPS。
- UseStaticFiles :静态文件中间件,返回静态文件,并简化进一步请求处理。
- UseCookiePolicy :Cookie 策略中间件
- UseRouting :用于路由请求的路由中间件
- UseAuthentication :身份验证中间件 ,尝试对用户进行身份验证,然后才会允许用户访问安全资源。
- UseAuthorization :用于授权用户访问安全资源
- UseSession :建立和维护会话状态,在 Cookie 策略中间件之后和 MVC 中间件之前调用会话中间件。
- 用于将 Razor Pages 终结点添加到请求管道的终结点路由中间件(带有 MapRazorPages 的 UseEndpoints)。
对中间件管道进行分支
- Map 扩展基于给定请求路径约定来创建管道分支
- MapWhen 基于给定谓词的结果创建请求管道分支
- UseWhen 也基于给定谓词的结果创建请求管道分支
UseWhen
与MapWhen
区别,如果这个分支不发生短路或包含终端中间件,UseWhen
会重新加入主管道
使用 IStartupFilter 扩展 Startup
在应用的中间件管道的开头或末尾配置中间件,而无需显式调用
Use{Middleware}
IStartupFilter.Configure
可以将中间件设置为在库添加的中间件之前或之后运行使用步骤:
创建自定义中间件,比如
RequestSetOptionsMiddleware
创建配置类实现 IStartupFilter 接口
public class RequestSetOptionsStartupFilter : IStartupFilter { public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next) { return builder => { builder.UseMiddleware<RequestSetOptionsMiddleware>(); next(builder); }; } }
在
Program.cs
中注册IStartupFilter
builder.Services.AddTransient<IStartupFilter, RequestSetOptionsStartupFilter>();