首页 > 其他分享 >中间件Middleware

中间件Middleware

时间:2024-03-19 15:13:38浏览次数:16  
标签:请求 Middleware 中间件 next 管道 context app

参考:https://learn.microsoft.com/zh-cn/aspnet/core/fundamentals/middleware/?view=aspnetcore-8.0

1、什么是中间件

中间件是一种装配到应用管道以处理请求(Request)和响应(Response)的组件。 每个组件:

  • 选择是否将请求传递到管道中的下一个组件。
  • 可在管道中的下一个组件前后执行工作。

请求委托(Request delegates)用于生成请求管道。 请求委托处理每个 HTTP 请求。

1.1、中间件的工作原理

多个中间件按照顺序关系形成请求管道,用来处理HTTP请求和响应。中间件本质上是一个用来处理HTTP请求与响应的类。

HTTP请求(Request)进入请求管道(Request Pipeline),将会创建一个对象,用于描述请求(Http Request)信息,也用于返回最终HTTP响应(Response)。

请求从一端进入,按照添加顺序通过各个中间件(Middleware),每个中间件都可以对传入的请求进行一些操作然后 传入下一个中间件 或 直接返回。而对于返回响应(HTTP Response)也会遍历进来时所经过的中间件,顺序与请求时的正好相反。

注意:

  • next()前的代码会在管道进入的阶段执行,next后的代码会在管道返回阶段进行执行。
  • 如果中间件最终没有返回HTTP Response, 将会提示HTTP 404 Not Found。

 

1.2、中间件顺序

下图显示了 ASP.NET Core MVC 和 Razor Pages 应用的完整请求处理管道。图中的“终结点”中间件为相应的应用类型(MVC 或 Razor Pages)执行筛选器管道。

MVC中间件:

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        //异常处理中间件
        app.UseExceptionHandler("/Home/Error");
        // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
        app.UseHsts();
    }
    
    app.UseHttpsRedirection();
    //静态文件中间件,为提供静态文件(如HTML、CSS、JavaScript、图像等)和目录浏览提供支持。
    //如果请求与文件匹配,则为终端。
    app.UseStaticFiles();
    //路由中间件
    app.UseRouting();
    //权限中间件
    app.UseAuthorization();
    //终端中间件,用于处理端点,如控制器和视图
    app.UseEndpoints(endpoints =>
    {
        //定义默认的路由规则,指定了控制器、操作和可选的ID参数。
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Home}/{action=Index}/{id?}");
    });
}

 

 

2、Map、Use、Run

Map:用来定义一个管道可以处理哪些请求。

Use和Run:用来定义管道,一个管道由若干个Use和一个Run组成,每个Use引入一个中间件,而Run用来执行最终的核心应用逻辑 。

 

.Net Core中多种方式注册中间件:

  • Use:以委托的方式注册中间件。
  • UseMiddleware:以类型的方式注册中间件,T表示中间件的类型。
  • Map:将特定的请求地址(path)与中间件绑定,即path匹配时执行该中间件。
  • MapWhen:定义一个逻辑判断委托,当判断为true时执行指定的中间件。
  • Run:表示一个断路的中间件,是执行并返回给上游的中间件,无后续中间件。

2.1、Map对中间件管道进行分支

Map 扩展用作约定来创建管道分支。 Map 基于给定请求路径的匹配项来创建请求管道分支。 如果请求路径以给定路径开头,则执行分支。

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.Map("/map1", HandleMapTest1);

app.Map("/map2", HandleMapTest2);

app.Run(async context =>
{
    await context.Response.WriteAsync("Hello from non-Map delegate.");
});

app.Run();

static void HandleMapTest1(IApplicationBuilder app)
{
    app.Run(async context =>
    {
        await context.Response.WriteAsync("Map Test 1");
    });
}

static void HandleMapTest2(IApplicationBuilder app)
{
    app.Run(async context =>
    {
        await context.Response.WriteAsync("Map Test 2");
    });
}
请求 响应
localhost:1234 Hello from non-Map delegate.
localhost:1234/map1 Map Test 1
localhost:1234/map2 Map Test 2
localhost:1234/map3 Hello from non-Map delegate.

 

2.2、Use链接

用 Use 将多个请求委托链接在一起。 next 参数表示管道中的下一个委托。 可通过不调用 next 参数使管道短路。 通常可在 next 委托前后执行操作。

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // 向应用程序的请求管道中添加一个Func委托,这个委托其实就是所谓的中间件。
    // context参数是HttpContext,表示HTTP请求的上下文对象
    // next参数表示管道中的下一个中间件委托,如果不调用next,则会使管道短路
    // 用Use可以将多个中间件链接在一起
    app.Use(async (context, next) =>
    {
        await context.Response.WriteAsync("MiddleWare(1)-In\n");
        await next();
        await context.Response.WriteAsync("MiddleWare(1)-Out\n");
    });
    app.Use(async (context, next) =>
    {
        await context.Response.WriteAsync("MiddleWare(2)-In\n");
        await next();
        await context.Response.WriteAsync("MiddleWare(2)-Out\n");
    });
    
    // Run方法向应用程序的请求管道中添加一个RequestDelegate委托
    // 放在管道最后面,作为终端中间件
    app.Run(async (context) =>
    {
        await context.Response.WriteAsync("MiddleWare(3)\n"); 
    });
}
////执行结果:
//MiddleWare(1)-In
//MiddleWare(2)-In
//MiddleWare(3)
//MiddleWare(2)-Out
//MiddleWare(1)-Out

 

3、自定义中间件

3.1、Use委托

app.Use(async (context, next) =>
{
    var cultureQuery = context.Request.Query["culture"];
    if (!string.IsNullOrWhiteSpace(cultureQuery))
    {
        var culture = new CultureInfo(cultureQuery);

        CultureInfo.CurrentCulture = culture;
        CultureInfo.CurrentUICulture = culture;
    }

    // Call the next delegate/middleware in the pipeline.
    await next(context);//参数可省略,ASP.NET自动给参数。
});

app.Run(async (context) =>
{
    await context.Response.WriteAsync(
        $"CurrentCulture.DisplayName: {CultureInfo.CurrentCulture.DisplayName}");
});

app.Run();

 

3.2、自定义中间件类

  • 具有类型为 RequestDelegate 的参数的公共构造函数。
  • 名为 Invoke 或 InvokeAsync 的公共方法。 此方法必须:
    • 返回 Task
    • 接受类型 HttpContext 的第一个参数。

构造函数和 Invoke/InvokeAsync 的其他参数由依赖关系注入 (DI) 填充。

以下示例中间件通过查询字符串设置当前请求的区域性:

using System.Globalization;

namespace Middleware.Example;

public class RequestCultureMiddleware
{
    private readonly RequestDelegate _next;

    public RequestCultureMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        var cultureQuery = context.Request.Query["culture"];
        if (!string.IsNullOrWhiteSpace(cultureQuery))
        {
            var culture = new CultureInfo(cultureQuery);

            CultureInfo.CurrentCulture = culture;
            CultureInfo.CurrentUICulture = culture;
        }

        // Call the next delegate/middleware in the pipeline.
        await _next(context);
    }
}

 通常,创建扩展方法以通过 IApplicationBuilder 公开中间件:

public static class RequestCultureMiddlewareExtensions
{
    public static IApplicationBuilder UseRequestCulture(
        this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<RequestCultureMiddleware>();
    }
}

调用中间件:

app.UseRequestCulture();

 

4、Middleware和Filter的区别

比较:

  • 中间件: 中间件是一种装配到应用程序管道以处理HTTP请求和响应的组件。每个组件可以选择是否将请求传递到管道中的下一个组件,并可以在管道中的任意点添加。
  • 过滤器: 过滤器是在ASP.NET Core MVC或Web API应用程序中用于拦截操作方法执行的组件。它们可以在执行前后执行逻辑,例如验证、日志记录、处理异常等。

中间件示例:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.Use(async (context, next) => {
        // 在调用下一个中间件之前可以做一些事情
        await context.Response.WriteAsync("Before next middleware \r\n");
        
        // 调用下一个中间件
        await next();
        
        // 在调用下一个中间件之后可以做一些事情
        await context.Response.WriteAsync("After next middleware \r\n");
    });
 
    // ... 其他中间件配置
}

过滤器示例:

public class MySampleFilter : IActionFilter
{
    public void OnActionExecuting(ActionExecutingContext context)
    {
        // 在动作方法执行之前可以做一些事情
    }
 
    public void OnActionExecuted(ActionExecutedContext context)
    {
        // 在动作方法执行之后可以做一些事情
    }
}
 
[ServiceFilter(typeof(MySampleFilter))]
public class HomeController : Controller
{
    public IActionResult Index()
    {
        return View();
    }
}

总结:

  • 中间件和过滤器都是一种AOP的思想,都用于处理HTTP请求和响应。但是它们处理HTTP请求的方式不同:中间件是基于管道的方式,而过滤器是基于特定动作或控制器的方式。
  • 中间件可以用于那些不是特定于业务领域的逻辑,以及需要在每个请求或大多数请求中发生的操作,更加底层。而过滤器关注的是如何实现业务。

标签:请求,Middleware,中间件,next,管道,context,app
From: https://www.cnblogs.com/xixi-in-summer/p/18081145

相关文章

  • node后端helmet中间件
    认识helmethelmet是一个Node.js的中间件,用于增强Web应用程序的安全性。它通过设置各种HTTP头来增加安全性,以防止一些常见的攻击。作用以下是一些helmet中间件可以帮助你处理的安全问题:设置HTTP头部:helmet可以设置诸如X-Frame-Options、X-XSS-Protection、S......
  • docker compose启动中间件-2024
    这里只展示yml文件怎么配置version:'3'services:mysql:image:mysql:5.7container_name:mysqlcommand:mysqld--character-set-server=utf8mb4--collation-server=utf8mb4_unicode_ci--lower_case_table_names=1restart:alwaysenvironment......
  • 服务器中间件的种类和日常使用
    服务器中间件是一种软件,它提供了在服务器上运行的应用程序之间的连接和通信的功能。不同的中间件提供了不同的功能和特性,以下是一些常见的服务器中间件的种类和日常使用。ApacheTomcat:Tomcat是一种开源的JavaServlet容器,用于运行JavaWeb应用程序。它支持JavaSe......
  • Scrapy 中间件
    1.爬取图片使用 ImagePipeLines需要安装Pillow环境安装:pipinstallPillow爬虫文件:importscrapyfrom..itemsimportDeepimgproItemclassImgSpider(scrapy.Spider):name='img'#allowed_domains=['www.xxx.com']start_urls=[�......
  • 消息中间件RabbitMQ的原理和使用
    一、什么是MQMQ是MessageQueue的简写,表示消息队列的意思,它是一种用于在应用程序之间传递消息的技术。多用于分布式系统之间进行通信,作为消息中间件使用。MQ的作用有应用解耦、异步提速、流量削峰填谷,当然也有缺点,加入MQ消息中间件会额外增加系统的外部依赖,是系统稳定性降低,同......
  • .Net Core(七) 管道和中间件
    简介管道.NETCore中的管道是一个用于处理HTTP请求的组件。它是ASP.NETCore应用程序的核心部分,负责将传入的HTTP请求传递给适当的处理程序并生成响应。管道由一系列中间件组成,每个中间件都可以对请求或响应进行操作,然后将其传递给下一个中间件或终止请求处理。中间件......
  • 数据库系列:大厂使用数据库中间件解决什么问题?
    相关文章数据库系列:MySQL慢查询分析和性能优化数据库系列:MySQL索引优化总结(综合版)数据库系列:高并发下的数据字段变更数据库系列:覆盖索引和规避回表数据库系列:数据库高可用及无损扩容数据库系列:使用高区分度索引列提升性能数据库系列:前缀索引和索引长度的取舍数据库系列:My......
  • 中间件
    代码#Defineherethemodelsforyourspidermiddleware##Seedocumentationin:#https://docs.scrapy.org/en/latest/topics/spider-middleware.htmlimportrandomfromscrapyimportsignals#usefulforhandlingdifferentitemtypeswithasingleinterfac......
  • FastAPI系列:中间件
    中间件介绍中间件是一个函数,它在每个请求被特定的路径操作处理之前,以及在每个响应返回之前工作装饰器版中间件1.必须使用装饰器@app.middleware("http"),且middleware_type必须为http2.中间件参数:request,call_next,且call_next它将接收request作为参数@app.middleware("h......
  • gin中间件&控制器
    中间件Gin框架允许开发者在处理请求的过程中,加入用户自己的钩子(Hook)函数。这个钩子函数就叫中间件,中间件适合处理一些公共的业务逻辑,比如登录认证、权限校验、数据分页、记录日志、耗时统计等。通俗的讲:中间件就是匹配路由前和匹配路由完成后执行的一系列操作路由中间件Gi......