OWIN(.NET 开放 Web 接口)的幕后故事

在本文中,我们将了解 OWIN 是什么以及它的创建历史。本文将帮助那些想知道它背后的人。

我们将了解一群人如何为 .NET 社区带来宝贵的想法。同样重要的是,微软已经接受了 OWIN,而 ASP.NET Core 基本上就是建立在这个想法之上的。

简单来说,OWIN 是 .NET 开放 Web 接口的缩写,是一种提供将 Web 服务器与 Web 应用程序解耦的规范。该规范也是所有 .NET 生态系统的开放标准。

OWIN 的官方定义是 --- "定义了 .NET Web 服务器和 Web 应用程序之间的标准接口。OWIN 接口的目标是解耦服务器和应用程序,鼓励开发用于 .NET Web 开发的简单模块,并通过成为开放标准来刺激 .NET Web 开发工具的开源生态系统。"

"规范"这个词可能会让您感到困惑,但它指的是标准化的契约/接口,规定了 Web 服务器和应用程序之间的通信方式。因此,这些东西不是具体的实现,而是告诉开发人员如何在 Web 服务器和 Web 应用程序之间进行通信。

故事

OWIN 的故事始于 2010 年,当时一群人受到其他编程语言库的启发,试图创建一个在 Web 服务器和 Web 应用程序/框架之间提供 HTTP 抽象的库。

有一天,一群正在开发自己的框架/库的人,Ryan Riley(Kayak 的创建者)向其他正在开发其框架/库的人发送了一封电子邮件,内容是分享知识和共同努力(因为他们正在开发相同和不同但互补的东西)。

2010 年 9 月 7 日,Ryan Riley 发送的第一封电子邮件如下所示。

然后,大家开始一起讨论,因为这个信息很有道理。他们开始通过 Google 群组进行合作。

首先,小组开会寻找解决问题的方法。主要问题是,

  • ASP.NET 与 IIS (System.Web.* 包) 耦合
  • ASP.NET 太重
  • IIS 太慢(旧版本)
  • 很难实现 REST(比如最小 API --- Sinatra -> DSL)

此外,.NET 社区需要能够与不同的轻量级 Web 服务器协同工作的解耦/独立、轻量级、高效的 Web 框架。

于是,一群人开始从 Rack(Ruby)和 WSGI(Python)中寻找灵感,开始解决这个问题。简单来说,Rack 和 WSGI 定义了 Web 服务器和 Web 应用程序之间的通用接口。

2010 年 9 月 27 日,第一稿来自 Benjamin van der Veen。

如您所见,该思想基于 Responder、Request 和 Response 接口。(它从服务器端提供某些抽象,并通过传递到应用程序端的 Request 和 Response 提供抽象。该思想通过接口提供标准化)

2010 年 11 月 29 日,该小组的一名成员 (Scott Koon) 创建了一个名为".NET HTTP Abstractions"的工作组(请查看 Google 群组)。

这群人就 Web 服务器包装器达成了共识。同时,他们确定了 .NET 开放 Web 接口 (OWIN) 的命名法,并开始编写规范。

此外,在规范开始时,一群人就宣布了目标。

  • 无依赖关系
  • 风格灵活
  • 服务器独立性

好吧,在编写规范的过程中,当然遇到了一些问题(我将跳过这部分,如果您想了解更多详细信息,可以查看 Google 群组和网站链接)。

经过一番头脑风暴和实验,大家找到了以下解决方案,如下所示。

他们专注于"Delegate Of Doom"(非正式术语),它限制了为 Web 服务器和应用程序之间的通信提供最小依赖性和契约(标准化)的模式或技术。这个想法是创建通信契约 + 通信管道。

他们决定创建一个入口点,为那些想要开始使用 OWIN 标准的人提供一个辅助库。这个库在Github上是开源的。

2011 年 7 月 25 日,OWIN 项目公开发布,标志着协作创建规范的开始。

最终,2012年12月,OWIN项目发布了其第一个正式版本1.0。

OWIN

本节将介绍总体思路。不涉及规格细节。

上图是 OWIN 的鸟瞰图。正如我之前所说,OWIN 只是提供 Web 服务器和 Web 应用程序之间的解耦通信。但请注意,OWIN 不是框架、库或实现。如果您查看 OWIN 规范,您将获得有关 Web 服务器和应用程序如何相互通信的规则或代码示例的详细信息。

要了解细节,有必要从参与者开始,这有助于理解 OWIN 的思想。

  • Web 框架: OWIN 之上的独立组件,公开自己的对象模型或 API,应用程序可使用这些模型或 API 来促进请求处理。Web 框架可能需要从 OWIN 语义转换的适配器层。
  • Web 应用程序:可能建立在 Web 框架之上的特定应用程序,使用 OWIN 兼容服务器运行。
  • 中间件:在服务器和应用程序之间形成管道的传递组件,用于检查、路由或修改特定目的的请求和响应消息。
  • 服务器:直接与客户端通信然后使用 OWIN 语义处理请求的 HTTP 服务器。服务器可能需要转换为 OWIN 语义的适配器层。
  • 主机:应用程序和服务器在其中执行的进程,主要负责应用程序的启动。某些服务器也是主机。

主要是,参与者对于任何 Web 应用程序来说都是必须的。因此,OWIN 指示他们所有人实现目标。

请注意,为了便于理解,我将用运行时事物来描述所有过程。部分解释可能超出了 OWIN 的范围。

Web 服务器和 Web 应用程序(Web 框架的顶层)之间的通信。因此,这些参与者也具有巨大的计算逻辑。这个想法带来了用于处理 Web 请求和响应生命周期的管道。这也依赖于管道架构,该架构提供实现 Web 服务器和 Web 应用程序之间的交叉关注点。

一切始于主机,它创建所需的环境和配置内容。在运行时,它应该由内置的 Web 服务器和位于框架顶部的应用程序组成。因此,Web 服务器基本上会监听 HTTP 请求,填充内容和一些数据结构,然后将它们发送到通信管道。

构建管道的想法始于中间件,它是所有部分的链或过滤器。中间件提供了一些横切关注点,并有助于处理请求和响应生命周期。当请求来自服务器时,将它们发送到第一个链/过滤器(中间件),然后请求将一个接一个地继续。管道末端的请求由应用程序处理并生成响应,响应以反向方式发生同样的事情。

到目前为止,我们已经解释了总体思路,您可以查看规范以了解更多细节。

OWIN的解决方案从以下开始。

using Environment = IDictionary<string, object>
using AppFunc = Func<Environment, Task>

嗯,比你想象的要容易一些!

  • 环境是包含所有需要的数据(包括请求和响应对象)的键值对。因此,当服务器和应用程序相互通信时,它是有意义的!
  • AppFunc 是处理请求的委托。

基本上,AppFunc 如何处理应用程序端的请求?代码如下所示。

using System.IO;
using System.Text;
using Headers = IDictionary<string, string[]>;
var app = AppFunc(env =>
{
    var bytes = Encoding.UTF8.GetBytes("Hello, OWIN!");
    var length = bytes.Length.ToString();
    var headers = env["owin.ResponseHeaders"];
    headers.Add("Content-Type", new[] { "text/plain" });
    headers.Add("Content-Length", new[] { length });
    var stream = (Stream)env["owin.ResponseBody"];
    return stream.WriteAsync(bytes, 0, bytes.Length);
});

AppFunc 上面的代码是中间件,它可以封装链中的下一个元素(即中间件)。并且它会调用下一个元素,以与其他元素相同的方式重复,就像一个嵌套链一样。

因此,它可以作为类和函数来实现。但我只展示类示例。

public class LoggingMiddleware
{
    private AppFunc _next;
    public LoggingMiddleware(AppFunc next)
    {
        this._next = next;
    }
    public Task LogBefore(Environment env)
    {
        // Implementation
    }
    public Task LogAfter(Environment env)
    {
        // Implementation
    }
    public async Task Invoke(Environment env)
    {
        LogBefore(env);
        await _next(env);
        LogAfter(env);
    }
}

这就是中间件方面。

还具有用于管道端的 IAppBuilder 接口。其主要目的是提供配置处理 HTTP 请求和响应的中间件管道的契约。

  • 最初旨在提供代表签名

  • 后来添加了 IAppBuilder 并作为唯一的接口

    public interface IAppBuilder
    {
    IDictionary<string, object> Properties { get; }
    IAppBuilder Use(object middleware, params object[] args);
    object Build(Type returnType);
    IAppBuilder New();
    }

可以看出,OWIN 解决方案仅依赖 FCL,因此依赖性极小。这些基本的东西有助于 OWIN 实现其目标。

PS 微软实现了 OWIN 的想法,它是 Katana,但这是另一个话题。

结论

OWIN 是一种规范,它提供了 Web 服务器和 Web 应用程序之间解耦的规则。此外,它还有助于实现 Web 服务器和应用程序之间的模块化架构。其背后的理念已在许多其他 Web 技术环境中得到应用。OWIN 是一个强大的理念,它为 .NET 社区提供了传统 IIS 和 ASP.NET(旧)托管模型的替代方案,解决了它们的局限性。

相关推荐
Envyᥫᩣ1 小时前
深入浅出C#编程语言
开发语言·c#
机器人天才一号4 小时前
C#从入门到放弃
开发语言·c#
吾与谁归in4 小时前
【C#设计模式(10)——装饰器模式(Decorator Pattern)】
设计模式·c#·装饰器模式
冷眼Σ(-᷅_-᷄๑)10 小时前
Path.Combine容易被忽略的细节
c#·.net
SongYuLong的博客16 小时前
C# (定时器、线程)
开发语言·c#
百锦再17 小时前
详解基于C#开发Windows API的SendMessage方法的鼠标键盘消息发送
windows·c#·计算机外设
无敌最俊朗@19 小时前
unity3d————协程原理讲解
开发语言·学习·unity·c#·游戏引擎
程序设计实验室19 小时前
在网页上调起本机C#程序
c#
Crazy Struggle1 天前
.NET 8 强大功能 IHostedService 与 BackgroundService 实战
c#·.net·.net core
fs哆哆1 天前
C#编程:优化【性别和成绩名次】均衡分班
开发语言·c#