Request请求进来,Middleware1=》Middleware2=》Middleware3,Response返回Middleware3=》Middleware2=》Middleware1
何为中间件?
1 public class Middleware 2 { 3 private readonly RequestDelegate _next; 4 5 public Middleware(RequestDelegate next) 6 { 7 _next = next; 8 } 9 10 public Task Invoke(HttpContext httpContext) 11 { 12 13 return _next(httpContext); 14 } 15 } 16 17 public delegate Task RequestDelegate(HttpContext context);
构造函数中接受一个RequestDelegate参数,invoke方法中接受HttpCointext参数。简而言之就是Func<RequestDelegate,RequestDelegate>
中间件如何串联?
查看源码!
IApplicationBuilder.Use方法其实就是在往components里添加中间件。
public IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware)
{
_components.Add(middleware);
return this;
}
IApplicationBuilder.Build方法,先将compoments集合反转循环遍历,把结果作为参数再传给下一个中间件。
1 public RequestDelegate Build() 2 { 3 RequestDelegate app = context => 4 { 5 // If we reach the end of the pipeline, but we have an endpoint, then something unexpected has happened. 6 // This could happen if user code sets an endpoint, but they forgot to add the UseEndpoint middleware. 7 var endpoint = context.GetEndpoint(); 8 var endpointRequestDelegate = endpoint?.RequestDelegate; 9 if (endpointRequestDelegate != null) 10 { 11 var message = 12 $"The request reached the end of the pipeline without executing the endpoint: ‘{endpoint.DisplayName}‘. " + 13 $"Please register the EndpointMiddleware using ‘{nameof(IApplicationBuilder)}.UseEndpoints(...)‘ if using " + 14 $"routing."; 15 throw new InvalidOperationException(message); 16 } 17 18 context.Response.StatusCode = 404; 19 return Task.CompletedTask; 20 }; 21 22 foreach (var component in _components.Reverse()) 23 { 24 app = component(app); 25 } 26 27 return app; 28 }
1 app.Use(next => { 2 Console.WriteLine("step 1"); 3 return async c => 4 { 5 await c.Response.WriteAsync("step 1 start"); 6 await next.Invoke(c); 7 await c.Response.WriteAsync("step 1 end"); 8 }; 9 }); 10 11 app.Use(next => { 12 Console.WriteLine("step 2"); 13 return async c => 14 { 15 await c.Response.WriteAsync("step 2 start"); 16 await next.Invoke(c); 17 await c.Response.WriteAsync("step 2 end"); 18 }; 19 }); 20 21 app.Use(next => { 22 Console.WriteLine("step 3"); 23 return async c => 24 { 25 await c.Response.WriteAsync("step 3 start"); 26 // await next.Invoke(c); 27 await c.Response.WriteAsync("step 3 end"); 28 }; 29 });
结果:
在控制台输出step 3,step 2,step 1 因为有Resverse,合理!
页面输出 step1 start step 2 start step 3 start step 3 end step 2 end step 1 end 对应管道模型
原文:https://www.cnblogs.com/xingzhu-nan/p/12535272.html