Middleware is software that is assembled into an application pipeline to handle requests and responses.

定义和使用

简单来说就是像单链表那样,使用 `(current, next)` 去串起来使用。

public IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware)
{
_components.Add(middleware);
return this;
}
  1. 具体使用:

     
    app.Use(next => {
    // _log("Use middleware xxx.");
    return async context => {
    // 在这里处理 Request
    await next(context);
    // 在这里处理 Response
    }
    })

    // 还有个写法的扩展
    app.Use(async (context, next) =>
    {
    await next();
    });
  2. 头 和 尾

    头和尾在程序集内已经给我们提供了,在 Hosting 的启动中,通过 Build 方法创建了一个 RequestDelegate 就是了:

     
    public RequestDelegate Build()
    {
    // 这个是默认的404中间件
    RequestDelegate app = context =>
    {
    context.Response.StatusCode = 404;
    return Task.CompletedTask;
    };
    // 在这里把这个默认的404中间件放在所以的最后,所以即有头又有尾了。
    foreach (var component in _components.Reverse()) { app = component(app); }
    return app;
    }
  3. 自己中止中间件的链路

  • 在自己的中间件里面,不调用 next(context) 就可以了。

  • 或者使用官方提供的 Run() 方法。

      
    app.Run(async context => { await context.Response.WriteAsync("Response end!"); });
  1. 针对特定场景的中间件

     
    app.UseWhen(context => context.Request.Path.StartsWithSegments("/api"), appBuilder =>
    {
    appBuilder.UseMiddleware_API_Handle();
    });
  2. 中间件分支

     
    // 这里注册的 Middleware a, b, c 还是会执行的。
    app.MapWhen(context => context.Request.Path.StartsWithSegments("/download"), appBuilder =>
    {
    appBuilder.UseMiddleware_Self_DownLoad_Handle();
    });
    // 和上面 UseWhen 不一样的是:这里的 Middleware x, y, z 就不会再继续执行了。
    // 而是基于当前的状态,克隆出一个新的分支。
  3. 基于路由的中间件分支功能,支持嵌套

     
    app.Map("/download", appBuilder =>{
    appBuilder.UseMiddleware_Self_DownLoad_Handle();
    })

    // Map 还比 MapWhen 多了一层 app.UsePathBase() 用于拆分请求路径
    // 下面两种写法是等价的。第二种有点别扭,因为我没想到具体的适应场景~
    app.Map("/Area", builder => { /* ... */ });

    app.MapWhen( context => context.Request.Path.StartsWithSegments("/Area"), builder => {
    builder.UsePathBase("/Area"); /* ... */
    });

标准模板

public class MyMiddleware
{
private readonly RequestDelegate _next;

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

public async Task Invoke(HttpContext httpContext, IMyService svc)
{
svc.MyProperty = 1000;
await _next(httpContext);
}
}
public static class MyMiddlewareExtensions
{
public static IApplicationBuilder UseMyMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<MyMiddleware>();
}
}

// 使用
public void Configure(IApplicationBuilder app)
{
// ...
app.UseMyMiddleware();
// ...
}

其他