中间件应该总是调用下一个?

2023-12-23

我一直在尝试了解 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 Invokemethod 是要返回的请求委托,它可以访问管道上的下一个委托。

然后,在编写中间件时,我们可以访问管道的下一个组件,但我有一个疑问。一开始我认为理想的方式始终是按以下方式工作:

  • 检查中间件是否可以处理请求
  • 如果可以的话,做任何必须做的事情HttpContext
  • 调用管道上的下一个中间件

因此,当我第一次研究这个时,我认为每个中间件都应该始终调用下一个中间件。但这样做会导致奇怪的行为,如上讨论的这个问题 https://stackoverflow.com/questions/28789305/why-the-404-middleware-behaves-like-this.

另外查看一些中间件的源代码,我发现其中一些中间件遵循另一个步骤:

  • 检查中间件是否可以处理请求
  • 如果可以的话,做任何必须做的事情HttpContext就这样
  • If not, 并且只有当不呼叫下一个

这是使用中间件的真正想法吗?哪种方法是正确的方法?每个中间件都会对请求执行必须执行的操作,并始终调用下一个中间件,或者如果中间件可以处理该请求,它就不再调用下一个中间件?

我相信中间件只有在无法处理请求时才应该调用下一个。我认为这是因为如果不这样做,管道上的中间件之间就会存在耦合。因此,为了处理请求,中间件需要知道前一个请求做了什么,以避免搞乱一切。这个结论对吗?


中间件的存在是为了使请求管道模块化,这意味着只要您遵守合同,您就可以从中添加/删除/替换部分。例如,如果您的应用程序在没有任何缓存的情况下提供某些文件,您可以在管道的前面添加一个中间件,而无需更改其余部分。它们是积木。

中间件可以:

  1. 不执行任何操作并进一步传递请求(例如,仅适用于 POST 请求但当前是 GET 请求的中间件)
  2. 没做什么根据要求,做其他事情并进一步传递(例如日志记录)
  3. 对请求执行某些操作并进一步传递请求(例如,获取身份验证令牌并将其转换为身份,或从请求中删除一些敏感信息)
  4. 结束管道并且不再传递请求(例如静态文件中间件 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同样:有两种类型的中间件:

  1. 旨在执行某些操作并进一步传递数据的中间件(例如身份验证、cookie、验证、日志记录等)
  2. 完成管道的中间件(静态文件、MVC 等)。

当然,有些人可能会根据具体情况两者都做。例如,如果凭据不正确,auth 可以结束管道,但否则继续。

中间件的作者必须决定是否应调用下一个中间件(如果有)。如果您的问题中的中间件返回一条消息,则它不应调用下一条消息。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

中间件应该总是调用下一个? 的相关文章

  • 属性对象什么时候创建?

    由于属性实际上只是附加到程序集的元数据 这是否意味着属性对象仅根据请求创建 例如当您调用 GetCustomAttributes 时 或者它们是在创建对象时创建的 或者 前两个的组合 在由于 CLR 的属性扫描而创建对象时创建 从 CLR
  • C++:无法使用scoped_allocator_adaptor传播polymorphic_allocator

    我有一个vector
  • 为什么 POSIX 允许在只读模式下超出现有文件结尾 (fseek) 进行搜索

    为什么寻找文件结尾很有用 为什么 POSIX 让我们像示例中那样在以只读方式打开的文件中进行查找 c http en cppreference com w c io fseek http en cppreference com w c io
  • 为什么禁止在 constexpr 函数中使用 goto?

    C 14 对你能做什么和不能做什么有规则constexpr功能 其中一些 没有asm 没有静态变量 看起来相当合理 但标准也不允许goto in constexpr功能 即使它允许其他控制流机制 这种区别背后的原因是什么 我以为我们已经过去
  • C# 用数组封送结构体

    假设我有一个类似于 public struct MyStruct public float a 我想用一些自定义数组大小实例化一个这样的结构 在本例中假设为 2 然后我将其封送到字节数组中 MyStruct s new MyStruct s
  • 当 Cortex-M3 出现硬故障时如何保留堆栈跟踪?

    使用以下设置 基于 Cortex M3 的 C gcc arm 交叉工具链 https launchpad net gcc arm embedded 使用 C 和 C FreeRtos 7 5 3 日食月神 Segger Jlink 与 J
  • 为什么模板不能位于外部“C”块内?

    这是一个后续问题一个答案 https stackoverflow com questions 4866433 is it possible to typedef a pointer to extern c function type wit
  • 在 ASP.Net Core 2.0 中导出到 Excel

    我曾经使用下面的代码在 ASP NET MVC 中将数据导出到 Excel Response AppendHeader content disposition attachment filename ExportedHtml xls Res
  • A* 之间的差异 pA = 新 A;和 A* pA = 新 A();

    在 C 中 以下两个动态对象创建之间的确切区别是什么 A pA new A A pA new A 我做了一些测试 但似乎在这两种情况下 都调用了默认构造函数 并且仅调用了它 我正在寻找性能方面的任何差异 Thanks If A是 POD 类
  • 使用安全函数在 C 中将字符串添加到字符串

    我想将文件名复制到字符串并附加 cpt 但我无法使用安全函数 strcat s 来做到这一点 错误 字符串不是空终止的 我确实设置了 0 如何使用安全函数修复此问题 size strlen locatie size nieuw char m
  • 用 C 实现 Unix shell:检查文件是否可执行

    我正在努力用 C 语言实现 Unix shell 目前正在处理相对路径的问题 特别是在输入命令时 现在 我每次都必须输入可执行文件的完整路径 而我宁愿简单地输入 ls 或 cat 我已经设法获取 PATH 环境变量 我的想法是在 字符处拆分
  • 检查 url 是否指向文件或页面

    我们需要以下内容 如果文件确实是文件 则从 URL 下载该文件 否则 如果它是一个页面 则什么也不做 举个简单的例子 我有以下命令来下载文件 My Computer Network DownloadFile http www wired c
  • 什么是 C 语言的高效工作流程? - Makefile + bash脚本

    我正在开发我的第一个项目 该项目将跨越多个 C 文件 对于我的前几个练习程序 我只是在中编写了我的代码main c并使用编译gcc main c o main 当我学习时 这对我有用 现在 我正在独自开展一个更大的项目 我想继续自己进行编译
  • 已过时 - OpenCV 的错误模式

    我正在使用 OpenCV 1 进行一些图像处理 并且对 cvSetErrMode 函数 它是 CxCore 的一部分 感到困惑 OpenCV 具有三种错误模式 叶 调用错误处理程序后 程序终止 Parent 程序没有终止 但错误处理程序被调
  • 如何构建印度尼西亚电话号码正则表达式

    这些是一些印度尼西亚的电话号码 08xxxxxxxxx 至少包含 11 个字符长度 08xxxxxxxxxxx 始终以 08 开头 我发现这个很有用 Regex regex new Regex 08 0 9 0 9 0 9 0 9 0 9
  • 如何在内存中存储分子?

    我想将分子存储在内存中 这些可以是简单的分子 Methane CH4 C H bond length 108 7 pm H H angle 109 degrees But also more complex molecules like p
  • ListDictionary 类是否有通用替代方案?

    我正在查看一些示例代码 其中他们使用了ListDictionary对象来存储少量数据 大约 5 10 个对象左右 但这个数字可能会随着时间的推移而改变 我使用此类的唯一问题是 与我所做的其他所有事情不同 它不是通用的 这意味着 如果我在这里
  • 在Linux中使用C/C++获取机器序列号和CPU ID

    在Linux系统中如何获取机器序列号和CPU ID 示例代码受到高度赞赏 Here http lxr linux no linux v2 6 39 arch x86 include asm processor h L173Linux 内核似
  • Bing 地图运行时错误 Windows 8.1

    当我运行带有 Bing Map 集成的 Windows 8 1 应用程序时 出现以下错误 Windows UI Xaml Markup XamlParseException 类型的异常 发生在 DistanceApp exe 中 但未在用户
  • 将变量分配给另一个变量,并将一个变量的更改反映到另一个变量中

    是否可以将一个变量分配给另一个变量 并且当您更改第二个变量时 更改会瀑布式下降到第一个变量 像这样 int a 0 int b a b 1 现在 b 和 a 都 1 我问这个问题的原因是因为我有 4 个要跟踪的对象 并且我使用名为 curr

随机推荐

  • 阻止直到按下按键或一天中的给定时间

    如何阻止直到 1 按键或 2 之前输入的一天中的时间 以较早者为准 hh mm格式已达到 我正在使用 Windows 以防万一 这DOS汇编程序 http www robvanderwoude com downloads batchman
  • Android Bundle 简单单元测试不起作用

    我对 android 很陌生 并试图了解捆绑包的工作原理 我被以下单元测试阻止 有人可以解释一下为什么失败吗 Test public void testBundle throws Exception Bundle bundle new Bu
  • 当“react-native run-ios”时端口 8081 已被使用

    是的 我已经读过这篇文章 但仍然不知道如何使其发挥作用 反应本机 端口 8081 已在使用中 打包器未运行或未正确运行命令 bin sh 失败 退出代码为 2 https stackoverflow com questions 302164
  • ES6 标记模板实用性

    我了解ES6的语法标记模板 https developer mozilla org en US docs Web JavaScript Reference template strings Tagged template strings 我
  • epoll_wait 中的 epoll 事件顺序

    我已将一个程序从 select 移植到 epoll 以增加我们可以处理的套接字数量 我已经将socket添加到epoll FD中并且可以愉快地读写了 但是 即使我使用级别触发事件 我也担心套接字可能会饥饿 我担心的情况是 准备好的套接字数量
  • 如何从函数中获取结果(输出)?以后如何使用结果?

    假设我有一个类似的函数 def foo x hello world 如何让函数返回x 这样我就可以将它用作另一个函数的输入或在程序体内使用该变量 我尝试使用return然后使用x另一个函数中的变量 但我得到了NameError那样 For
  • Rails - url_for 在使用命名空间时表现不同(基于当前使用的控制器)

    假设命名空间是 abc 我们有一个控制器 abcs 另一个使用命名空间 abc 的控制器是 defs 为了便于理解 AbcsController Abc DefsController 当电流处于AbcsController url for
  • 使用现有字符串定义定义“resValue”

    我更感兴趣的是在 strings xml 文件而不是 build gradle 中定义我的应用程序的多种风格 鉴于多种风格 我想要一个简化的发布 调试变体 buildTypes release signingConfig signingCo
  • 依赖类型的 ghc-7.6 类实例

    异构列表是 ghc 7 6 的新依赖类型工具给出的示例之一 data HList gt where HNil HList HCons a gt HList t gt HList a t 示例列表 li 编译良好 li HCons Int H
  • Windows Phone 8.1:设备唯一 ID 的 DeviceExtendedProperties 或 DeviceStatus

    我想获取 Windows Phone 中的设备 ID8 1 The 设备扩展属性 http msdn microsoft com library windows apps microsoft phone info deviceextende
  • 让链接执行 2 个操作

    首先 我不知道我是否采取了正确的方法来解决这个问题 所以请耐心等待 我的问题如下 我尝试使用手风琴 其中每个选项卡都是一个类别 展开时 手风琴会显示该类别中的艺术家 到目前为止 一切都很好 现在 我想要实现的另一部分是 一旦我单击选项卡 其
  • 使用 GORM 和 Postgresql 时如何节省 Go 中数据库的时间?

    我目前正在解析时间字符串并将其保存到数据库 Postgresql event Time time Parse 3 04 PM 9 00 PM value of event Time now is 0000 01 01 21 00 00 00
  • Apache Ignite 使用 Spring-Boot 加载两次?

    我正在使用 Spring Boot 1 2 7 RELEASE 和 Apache Ignite 1 4 0 进行原型设计 并注意到有些奇怪的东西 也许这只是一个日志配置 看起来 Apache Ignite 正在尝试用 Spring 启动两次
  • 在重定向之前设置 cookie

    我试图在标头重定向之前设置 cookie 但它不起作用 我读过在标头重定向行之后设置 cookie 应该可以解决问题 但我没有运气 同样 之前的一篇文章建议 如果您在位置重定向中使用 人类 URL 则应该在 cookie 的路径参数中使用
  • 在 Interface Builder 中将文本标记为不需要翻译

    我在 Interface Builder 中使用虚拟文本 这是一个例子 The MYNAME不是真正的界面文本 它是以编程方式设置的viewDidLoad 我可以用特殊方式标记它 以便默认将其从我的翻译文件中排除吗 如果您正在使用ibtoo
  • Capistrano 使用 sudo 甚至使用“set :use_sudo, false”

    我不希望使用 sudo 通过 Capistrano 执行任何远程命令 具体来说 当我跑步时cap deploy setup 第一次时要求我输入 sudo 密码mkdir命令 我添加了set use sudo false到我的deploy r
  • SqlCipher Mingw/msys 问题

    我有一个问题 我无法编译 SqlCipher 我正在用这个http groups google com group sqlcipher browse thread thread 55c6296b56bf4533 c792bbec6df7d4
  • 如何在jquery中引用JSF组件Id? [复制]

    这个问题在这里已经有答案了 我如何在 jquery 中引用 JSF 组件 因为我不知道要引用的组件 id 前面的 id 你可以付出一切NamingContainer http download oracle com javaee 6 api
  • Prometheus-如何监控其他docker容器

    我想用普罗米修斯监控我的docker容器 我可以跑普罗米修斯 with Grafana但我不知道如何指示它监视其他 docker 容器 如果可能的话我想看一些例子 例如我有Ubuntu在我的主机上运行的容器以及Gentoo容器 我如何告诉
  • 中间件应该总是调用下一个?

    我一直在尝试了解 ASP NET 5 管道中间件的真正工作原理 据我所知 中间件只是一个Func