我一直在尝试了解 ASP.NET 5 管道中间件的真正工作原理。据我所知,中间件只是一个Func<RequestDelegate, RequestDelegate>
,它是一个指向方法的指针,该方法接收对下一个请求委托的引用并返回包装下一个请求委托的新委托。当然,我们可以使用类来表示中间件,例如:
public class MyMiddleware
{
private readonly _next;
public MyMiddleware(RequestDelegate next)
{
if (next == null)
{
throw new ArgumentNullException("next");
}
_next = next;
}
public Task Invoke(HttpContext context)
{
// New request delegate code here which can wrap the next one on the pipeline
}
}
自从RequestDelegate
是一个委托,可以保存对接收方法的引用HttpContext
并返回一个Task
the Invoke
method 是要返回的请求委托,它可以访问管道上的下一个委托。
然后,在编写中间件时,我们可以访问管道的下一个组件,但我有一个疑问。一开始我认为理想的方式始终是按以下方式工作:
- 检查中间件是否可以处理请求
- 如果可以的话,做任何必须做的事情
HttpContext
- 调用管道上的下一个中间件
因此,当我第一次研究这个时,我认为每个中间件都应该始终调用下一个中间件。但这样做会导致奇怪的行为,如上讨论的这个问题 https://stackoverflow.com/questions/28789305/why-the-404-middleware-behaves-like-this.
另外查看一些中间件的源代码,我发现其中一些中间件遵循另一个步骤:
- 检查中间件是否可以处理请求
- 如果可以的话,做任何必须做的事情
HttpContext
就这样
- If not, 并且只有当不呼叫下一个
这是使用中间件的真正想法吗?哪种方法是正确的方法?每个中间件都会对请求执行必须执行的操作,并始终调用下一个中间件,或者如果中间件可以处理该请求,它就不再调用下一个中间件?
我相信中间件只有在无法处理请求时才应该调用下一个。我认为这是因为如果不这样做,管道上的中间件之间就会存在耦合。因此,为了处理请求,中间件需要知道前一个请求做了什么,以避免搞乱一切。这个结论对吗?
中间件的存在是为了使请求管道模块化,这意味着只要您遵守合同,您就可以从中添加/删除/替换部分。例如,如果您的应用程序在没有任何缓存的情况下提供某些文件,您可以在管道的前面添加一个中间件,而无需更改其余部分。它们是积木。
中间件可以:
- 不执行任何操作并进一步传递请求(例如,仅适用于 POST 请求但当前是 GET 请求的中间件)
- 没做什么根据要求,做其他事情并进一步传递(例如日志记录)
- 对请求执行某些操作并进一步传递请求(例如,获取身份验证令牌并将其转换为身份,或从请求中删除一些敏感信息)
- 结束管道并且不再传递请求(例如静态文件中间件 https://github.com/aspnet/StaticFiles/blob/dev/src/Microsoft.AspNet.StaticFiles/StaticFileMiddleware.cs当路由匹配时,它只返回文件或 MVC)
可能会回答你的其他问题 https://stackoverflow.com/questions/28789305/why-the-404-middleware-behaves-like-this同样:有两种类型的中间件:
- 旨在执行某些操作并进一步传递数据的中间件(例如身份验证、cookie、验证、日志记录等)
- 完成管道的中间件(静态文件、MVC 等)。
当然,有些人可能会根据具体情况两者都做。例如,如果凭据不正确,auth 可以结束管道,但否则继续。
中间件的作者必须决定是否应调用下一个中间件(如果有)。如果您的问题中的中间件返回一条消息,则它不应调用下一条消息。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)