[netcore] ASP.NET Core 中间件
Posted 厦门德仔
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[netcore] ASP.NET Core 中间件相关的知识,希望对你有一定的参考价值。
基本概念
中间件是一种装配到应用管道以处理请求和响应的软件。 每个组件:
选择是否将请求传递到管道中的下一个组件。
可在管道中的下一个组件前后执行工作。
请求委托用于生成请求管道。 请求委托处理每个 HTTP 请求。
使用 RunMap 和 Use 扩展方法来配置请求委托。 可将一个单独的请求委托并行指定为匿名方法(称为并行中间件),或在可重用的类中对其进行定义。 这些可重用的类和并行匿名方法即为中间件,也叫中间件组件。 请求管道中的每个中间件组件负责调用管道中的下一个组件,或使管道短路。 当中间件短路时,它被称为“终端中间件”,因为它阻止中间件进一步处理请求。
将 HTTP 处理程序和模块迁移到 ASP.NET Core 中间件介绍了 ASP.NET Core 和 ASP.NET 4.x 中请求管道之间的差异,并提供了更多的中间件示例。
WHY
中间件是ASP.NET Core的核心组件:
MVC框架,响应缓存,身份验证,CORS,Swagger等都是内置中间件。
什么是中间件
1.广义上来讲:Tomcat,WebLogic,Redis,IIS;狭义上来讲,ASP.NET Core中的中间件指ASP.NET Core 中的一个组件。
2.中间件由前逻辑,next,后逻辑3部分组成,前逻辑为第一段要执行的逻辑代码,next为指向下一个中间件的调用,后逻辑为从下一个中间件执行返回所执行的逻辑代码。每个HTTP请求都要经历一系列中间件的处理,每个中间件对于请求特定的处理后,再转到下一个中间件,最终的业务逻辑代码执行完成后,响应的内容也会按照处理的相反顺序进行处理,然后形成HTTP响应报文返回给客户端。
3.中间件组成一个管道,整个ASP.NET CORE的执行过程就是HTTP请求和响应按照中间件组装的顺序再中间之间流转的过程,开发人员可以对组成管道的中间件按照需要进行自由组合
中间件的三个概念
Map,Use和Run.Map用来定义一个管道可以处理那些请求,Use和Run来定义管道,一个管道由若干个use和一个Run组成,每个Use引入一个中间件,而run是用来执行最终核心的应用逻辑
每个委托均可在下一个委托前后执行操作。 应尽早在管道中调用异常处理委托,这样它们就能捕获在管道的后期阶段发生的异常。
尽可能简单的 ASP.NET Core 应用设置了处理所有请求的单个请求委托。 这种情况不包括实际请求管道。 调用单个匿名函数以响应每个 HTTP 请求。
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Run(async context =>
await context.Response.WriteAsync("Hello world!");
);
app.Run();
用 Use 将多个请求委托链接在一起。 next 参数表示管道中的下一个委托。 可通过不调用 next 参数使管道短路。 通常可在 next 委托前后执行操作,如以下示例所示:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Use(async (context, next) =>
// Do work that can 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.");
);
app.Run();
当委托不将请求传递给下一个委托时,它被称为“让请求管道短路”。 通常需要短路,因为这样可以避免不必要的工作。 例如,静态文件中间件可以处理对静态文件的请求,并让管道的其余部分短路,从而起到终端中间件的作用。 如果中间件添加到管道中,且位于终止进一步处理的中间件前,它们仍处理 next.Invoke 语句后面的代码。 不过,请参阅下面有关尝试对已发送的响应执行写入操作的警告
Run 委托不会收到 next 参数。 第一个 Run 委托始终为终端,用于终止管道。 Run 是一种约定。 某些中间件组件可能会公开在管道末尾运行的 Run[Middleware] 方法:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Use(async (context, next) =>
// Do work that can 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.");
);
app.Run();
在前面的示例中,Run 委托将 “Hello from 2nd delegate.” 写入响应,然后终止管道。 如果在 Run 委托之后添加了另一个 Use 或 Run 委托,则不会调用该委托。
中间件顺序
下图显示了 ASP.NET Core MVC 和 Razor Pages 应用的完整请求处理管道。 你可以在典型应用中了解现有中间件的顺序,以及在哪里添加自定义中间件。 你可以完全控制如何重新排列现有中间件,或根据场景需要注入新的自定义中间件
图中的“终结点”中间件为相应的应用类型(MVC 或 Razor Pages)执行筛选器管道。
上一个图中的路由中间件显示在以下静态文件中。 这是通过显式调用 app.UseRouting 实现项目模板的顺序。 如果不调用 app.UseRouting,路由中间件将默认在管道开头运行。 有关详细信息,请参阅路由。
对中间件管道进行分支
Map 扩展用作约定来创建管道分支。 Map 基于给定请求路径的匹配项来创建请求管道分支。 如果请求路径以给定路径开头,则执行分支。
做个简单测试:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
//app.MapGet("/", () => "Hello World!");
//app.MapGet("/test", () => "gdh");
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 context =>
await context.Response.WriteAsync("Run <br/>");
);
);
app.Run();
运行效果:
同样支持嵌套,请自行验证。
内置中间件
ASP.NET Core 附带以下中间件组件。 “顺序”列提供备注,以说明中间件在请求处理管道中的放置,以及中间件可能会终止请求处理的条件。 如果中间件让请求处理管道短路,并阻止下游中间件进一步处理请求,它被称为“终端中间件”。 若要详细了解短路,请参阅使用 IApplicationBuilder 创建中间件管道部分。
中间件 | 描述 | 顺序 |
---|---|---|
身份验证 | 提供身份验证支持。 | 在需要 HttpContext.User 之前。 OAuth 回叫的终端。 |
授权 | 提供身份验证支持。 | 紧接在身份验证中间件之后。 |
Cookie 策略 | 跟踪用户是否同意存储个人信息,并强制实施 cookie 字段(如 secure 和 SameSite)的最低标准。 | 在发出 cookie 的中间件之前。 示例:身份验证、会话、MVC (TempData)。 |
CORS | 配置跨域资源共享。 | 在使用 CORS 的组件之前。 由于此错误,UseCors 当前必须在 UseResponseCaching 之前运行。 |
DeveloperExceptionPage | 生成一个页面,其中包含的错误信息仅适用于开发环境。 | 在生成错误的组件之前。 对于开发环境,项目模板会自动将此中间件注册为管道中的第一个中间件。 |
诊断 | 提供新应用的开发人员异常页、异常处理、状态代码页和默认网页的几个单独的中间件。 | 在生成错误的组件之前。 异常终端或为新应用提供默认网页的终端。 |
转接头 | 将代理标头转发到当前请求。 | 在使用已更新字段的组件之前。 示例:方案、主机、客户端 IP、方法。 |
运行状况检查 | 检查 ASP.NET Core 应用及其依赖项的运行状况,如检查数据库可用性。 | 如果请求与运行状况检查终结点匹配,则为终端。 |
标头传播 | 将 HTTP 标头从传入的请求传播到传出的 HTTP 客户端请求中。 | |
HTTP | 日志记录 记录 HTTP 请求和响应。 | 中间件管道的开头。 |
HTTP | 方法重写 允许传入 POST 请求重写方法。 | 在使用已更新方法的组件之前。 |
HTTPS | 重定向 将所有 HTTP 请求重定向到 HTTPS。 | 在使用 URL 的组件之前。 |
HTTP | 严格传输安全性 (HSTS) 添加特殊响应标头的安全增强中间件。 | 在发送响应之前,修改请求的组件之后。 示例:转接头、URL 重写。 |
MVC | 用 MVC/Razor Pages 处理请求。 | 如果请求与路由匹配,则为终端。 |
OWIN | 与基于 OWIN 的应用、服务器和中间件进行互操作。 | 如果 OWIN 中间件处理完请求,则为终端。 |
请求解压缩 提供对解压缩请求的支持。 在读取请求正文的组件之前。 | ||
响应缓存 | 提供对缓存响应的支持。 | 在需要缓存的组件之前。 UseCORS 必须在 UseResponseCaching 之前。 |
响应压缩 | 提供对压缩响应的支持。 | 在需要压缩的组件之前。 |
请求本地化 | 提供本地化支持。 | 在对本地化敏感的组件之前。 使用 RouteDataRequestCultureProvider 时,必须在路由中间件之后显示。 |
终结点路由 | 定义和约束请求路由。 | 用于匹配路由的终端。 |
SPA | 通过返回单页应用程序 (SPA) 的默认页面, | 在中间件链中处理来自这个点的所有请求 在链中处于靠后位置,因此其他服务于静态文件、MVC 操作等内容的中间件占据优先位置。 |
会话 | 提供对管理用户会话的支持。 | 在需要会话的组件之前。 |
静态文件 | 为提供静态文件和目录浏览提供支持。 | 如果请求与文件匹配,则为终端。 |
URL 重写 | 提供对重写 URL 和重定向请求的支持。 | 在使用 URL 的组件之前。 |
W3CLogging | 以 W3C 扩展日志文件格式生成服务器访问日志。 | 中间件管道的开头。 |
WebSockets | 启用 WebSockets 协议。 | 在接受 WebSocket 请求所需的组件之前。 |
更多请参考微软官方文档
以上是关于[netcore] ASP.NET Core 中间件的主要内容,如果未能解决你的问题,请参考以下文章