4

我有一个关于 OWIN 管道的简单问题。我非常了解这个规范的整个概念,但有些东西我还没有完全消化。

根据网上的几篇帖子,有一个 OWIN 管道,它由几个开发人员定义的模块(或中间件组件)组成,由 owin Host 构建。然后是服务器,它将侦听请求并将它们传递给 = 通过 OWIN 组件的管道。

我不完全理解的一点是为什么我们需要管道。例如,让我们想象在 StartUp 类中我们有类似的东西:

public class Startup
{
   public void Configuration(IAppBuilder app)
   {
      app.Use<CustomMiddleware>(new CustomComponent());
      var config = new HubConfiguration { EnableCrossDomain = true };
      app.MapHubs(config);
      string exeFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
      string webFolder = Path.Combine(exeFolder, "Web");
      app.UseStaticFiles(webFolder);
   }
}

在上面的示例中,我们要求 OWIN 主机构建三个 OWIN 中间件组件的管道。据我了解,服务器会将请求(可能包含在字典中)转发到该管道中的第一个组件,然后该组件将执行一些任务并将其传递给下一个组件,依此类推。

我想知道为什么我们需要获取每个请求中涉及的所有组件;例如,如果我们只要求静态 html 页面,为什么不只打扰处理静态文件的组件呢?我的意思是为什么这样的请求需要 Web Api 的参与。

4

3 回答 3

3

我想我已经清除了。事实证明,请求不必通过整个管道。管道中的每个组件负责决定是否可以处理请求或是否要将请求转发到下一个节点;

于 2013-09-20T07:58:18.010 回答
2

您的回答是正确的,中间件可能会选择不处理请求。许多 Katana 中间件实现支持“软 404”方法,其中中间件将 404 解释为“尝试next中间件”。第一个完成的中间件Task将停止进一步传播并完成响应消息。您可以通过以最可能的顺序插入中间件来优化路径,以提高性能或通用性。

于 2014-09-25T21:06:26.120 回答
1

中间件组件按顺序执行,通常需要遍历管道中的所有组件,直到其中一个组件决定不调用下一个组件来切断管道。

这是可能的,因为每个中间件组件都有一个对下一个的引用,以及environment,一个对象字典,其键是一个字符串,它可以访问所有必要的东西来检查请求、创建响应和执行许多操作其他事情。(使用字典很聪明,因为很容易添加任何类型的信息或可执行代码,这是事先不知道的)。

每个组件都可以做以下事情,但它们都是可选的:

  • 在调用下一个组件之前执行代码(通常检查和修改环境字典)
  • 调用管道的下一个中间件组件(将执行相同的操作)
  • 在下一个组件完成执行后执行一些代码
  • 抛出异常(故意或由于未处理的错误)

管道执行将在以下一种情况下完成:

  • 中间件组件不调用下一个
  • 中间件组件抛出异常

注意:每个“中间件组件”都是 应用程序委托的实现

如果它们以正确的顺序注册,那么拥有一堆组件是有意义的。管道可能看起来像这样:

  • 验证
  • 授权
  • 缓存
  • 执行某种 API 或 HTML 生成

每个组件都有足够的信息来执行其负责的代码。例如:

  • 将始终执行身份验证,并在字典中设置主体的信息。然后它会调用下一个:授权组件
  • 根据请求和身份验证的结果,授权组件将决定主体是否具有执行请求的权限,并调用下一个组件(缓存),或者拒绝请求
  • 缓存还可以决定它是否可以返回缓存结果,或者必须调用下一个组件
  • 最后一个组件将执行,并且可能会创建响应,并且不会调用任何其他组件。调用堆栈将以相反的顺序运行,使每个组件都有可能进行一些 estra 工作。例如,缓存组件可以缓存响应,而下一个(授权和身份验证)将简单地返回而不执行任何额外的代码。

由于每个组件都有所有的请求、响应、上下文和任何其他所需的信息,它们都有足够的信息来决定他们是否必须做某事、修改字典、调用下一个或返回...

因此,如您所见,注册大量中间件组件并不需要对每个请求都执行所有这些组件,但有时这样做是有意义的。

OTOH 执行中间件组件可能非常便宜。例如,如果请求不需要授权,身份验证可以简单地执行下一个组件。cahin 组件也是如此,如果不需要缓存,它可以简单地调用下一个组件。

因此,即使一个组件在管道中,它也可以进行廉价的执行,或者根据请求甚至根本不运行。

在您的静态文件和 Web API 的特定问题中,其中一个组件将在另一个之前重新设置。第一个,无论是哪个,都会执行并创建响应,或者只是调用下一个,具体取决于请求。例如,如果静态文件在其他文件之前注册,如果请求文件,则静态文件将创建响应,并且不会调用 Web API。如果请求不是针对文件,它只会调用下一个组件:Web API 组件。

于 2015-03-14T17:29:45.983 回答