中间件是一种插入到管道上进行处理请求和响应的软件; 每个中间件组件具有下面的功能:
选择是否把请求传递到管道上的下一个组件
可以在下一个组件的之前和之后做处理工作
请求委托 (request delegate) 是用于建立 (build) 请求管道的, 请求委托可以处理每个 Http 的请求;
请求委托被配置的方法有三种: Run,Map,Use 扩展方法;
用 IApplicationBuilder 创建中间件管道
请求管道由一系列请求委托组成, 一个调用一个; 如下图
每个委托都可以在下一个委托之前和之后执行. 异常处理的委托在管道中被尽早调用, 因为它可以捕获到后面管道中发生的错误.
单个的请求委托可以使用 run
使用一个匿名函数处理每个 Http 请求; 并且使用的是 run , 它表示管道的结束, 即最后一个中间件, 不会再传递到下一个中间件
- public class Startup
- {
- public void Configure(IApplicationBuilder App)
- {
- App.Run(async context =>
- {
- await context.Response.WriteAsync("Hello, World!");
- });
- }
- }
链式的多个请求委托在一起, 使用 use
next 参数 代表管道中的下一个委托, 可以在下一个委托之前和之后进行处理; 你也可以不调用 next 参数, 直接短路管道(即不会传递到下一个委托 / 中间件).
- 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 方法的顺序决定了中间件顺序处理请求和逆序处理响应. 所以, 添加顺序是很重要的
一般的应用中的 Startup.Configure 方法添加中间组件的顺序:
- Exception/error handling
- HTTP Strict Transport Security Protocol
- HTTPS redirection
- Static file server
- Cookie policy enforcement
- Authentication
- Session
- 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
来源: https://www.cnblogs.com/Vincent-yuan/p/10771983.html