Writing custom middleware
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;
}
具体使用:
app.Use(next => {
// _log("Use middleware xxx.");
return async context => {
// 在这里处理 Request
await next(context);
// 在这里处理 Response
}
})
// 还有个写法的扩展
app.Use(async (context, next) =>
{
await next();
});头 和 尾
头和尾在程序集内已经给我们提供了,在 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;
}自己中止中间件的链路
在自己的中间件里面,不调用
next(context)
就可以了。或者使用官方提供的
Run()
方法。app.Run(async context => { await context.Response.WriteAsync("Response end!"); });
针对特定场景的中间件
app.UseWhen(context => context.Request.Path.StartsWithSegments("/api"), appBuilder =>
{
appBuilder.UseMiddleware_API_Handle();
});中间件分支
// 这里注册的 Middleware a, b, c 还是会执行的。
app.MapWhen(context => context.Request.Path.StartsWithSegments("/download"), appBuilder =>
{
appBuilder.UseMiddleware_Self_DownLoad_Handle();
});
// 和上面 UseWhen 不一样的是:这里的 Middleware x, y, z 就不会再继续执行了。
// 而是基于当前的状态,克隆出一个新的分支。基于路由的中间件分支功能,支持嵌套
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();
// ...
}