NET Core HTTP 管道

ASP.NET Core HTTP 管道中的那些事儿

前言

马上2016年就要过去了,时间可是真快啊。

上次写完 Identity 系列之后,反响还不错,所以本来打算写一个 ASP.NET Core 中间件系列的,但是中间遇到了很多事情。首先是 NPOI 的移植工作,移植过后还有一些Bug需要修复,然后一个事情是一个有关于分布式架构中消息一致性的一个中间件设计开发工作,还有就是博客还要坚持写,最后就是还有好几本书需要读,以及消化学习,所以深深感觉到时间不够用。废话不多说了,进入主题。

大部分中间件都是要依赖于 HTTP 管道和 HttpAbstractions 提供的上下文的,所以有必要先介绍一下 ASP.NET Core 在管道中封装了什么,了解清楚之后有助于更高的进阶学习。你看不懂也没有关系,对这些概念有一个认识就可以了,不需要你精通每一步都具体做了哪些东西,达到会用就是我的目的。因为我觉得随着你以后开发的深入,对这些东西使用多了之后,自然会想了解更多,到那个时候,你就会去看源码了。

IApplicationBuilder

IApplicationBuilder 是应用大家最熟悉它的地方应该就是位于 Startup.cs 文件中的 Configure 方法了吧

public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
    app.UseDeveloperExceptionPage();
    app.UseStaticFiles();
    app.UseMvc();
}

IApplicationBuilder 就像其名字一样,其实很简单,就是对内做了一个接口封装,对外提供了一个扩展,具体来说就是

对内封装了

  • IServiceProvider ApplicationServices { get; set; }:应用程序使用的服务,就是ConfigureServices注入的那些。
  • IFeatureCollection ServerFeatures { get; }: 工具箱对象,下面会提到的。
  • IDictionary<string, object> Properties { get; } :横跨各个中间件,在他们之间共享数据。

对外扩展了

  • IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware):注册中间件

还有一个 Build 用来返回管道最终的 HttpContext 状态

  • RequestDelegate Build(); : 最终的 RequestDelegate 形态

没什么复杂的东西,就这几个东西需要了解,下面是一个 IApplicationBuilder 的贴图,看起来应该会更直观。

那 RequestDelegate 又是什么东西呢?

RequestDelegate

RequestDelegate 是一个委托,是以委托形式对 HttpContext 的封装,在 ASP.NET Core 中也是非常重要的一个对象,先看一下定义吧。

namespace Microsoft.AspNetCore.Http
{
    public delegate Task RequestDelegate(HttpContext context);
}

为什么说这个对象很重要呢,因为在管道中所有的中间件都是直接或者间接的使用到它来做一些功能,因为它包装这 HttpContext 的嘛,而在Web开发中 HttpContext 的地位又是如此的高,接下来就说说 HttpContext

HttpContext

HttpContext 应该是做Web开发最熟悉的一个对象了,在这个对象中,封装着Http整个管道中的关键对象信息,这个对象同时伴随着整个管道中传输,也就是会经历整个请求的生命周期,所以这个对象非常重要,也是学习Web开发的一个基础知识。

与传统 .NET Framework 中的 System.Web.HttpContext 不同的是,在 ASP.NET Core 中 HttpContext 是一个抽象类,位于 Microsoft.AspNetCore.Http 命名空间下。它有一个默认的实现叫 DefaultHttpContext 位于 Microsoft.AspNetCore.Http 程序集。

我们知道以前的 System.Web.HttpContext 是怎么创建的吧?

在传统ASP.NET程序中,IIS接收到请求之后,会交给 aspnet_isapi.dll 这个程序集,程序集启动 ASP.NET 运行环境,然后调用 ISAPIRuntime 进行封装,封装之后就是一个 HttpWorkRequest 对象了,然后由 HttpRuntime将其转化为一个HttpContext。

所以在System.Web.HttpContext中,其构造函数为 HttpWorkerRequest

namespace System.Web
{
    public sealed class HttpContext : IServiceProvider, IPrincipalContainer
    {
        public HttpContext(HttpWorkerRequest wr);
    }
}

也就是说其实构建HttpContext所有的信息都是来自于 IIS 传递下来的 HttpWorkerRequest

现在,忘了它吧,是的全部忘掉,这个时候你又要骂微软了,尼玛当年为了面试这个东西不知道背了多少遍。 =_=

没办法,时代要发展要进步,我们也需要不断的学习,那在 ASP.NET Core 中,没有了 IIS ,它的 HttpContext 又是如何生成的呢? 构建 HttpContext 所需的信息又怎么来的呢? 客官不要着急,听我慢慢分解

IFeatureCollection

这里就需要先说一下另外一个比较重要接口了,它就是 IFeatureCollection 接口,这个接口是干嘛的呢? 我们先看一下它的定义:

public interface IFeatureCollection : IEnumerable<KeyValuePair<Type, object>>
{

    bool IsReadOnly { get; }

    int Revision { get; }

    object this[Type key] { get; set; }

    TFeature Get<TFeature>();

    void Set<TFeature>(TFeature instance);
}

看到这个接口的定义应该能够明白其功能了,接口继承于IEnumerable<KeyValuePair<Type, object>> 说明接口是一个键值对的集合,我们给接口取个名字吧,叫“工具箱”。

有些同学应该猜出来了,是的,ASP.NET Core中构建 HttpContext 就是所有需要的组件都是来自于 工具箱,那么 工具箱 里面都有什么呢?可以看到工具箱里面有 IHttpRequestFeature, IHttpResponseFeature, ISessionFeature 等等还有很多就不一一列举了,正是由于这一个一个的工具箱里面的工具,最终构建成为了整个 HttpContext 对象。我们来看一下 HttpContext 对象的构造函数:

namespace Microsoft.AspNetCore.Http
{
    public class DefaultHttpContext : HttpContext
    {
        public DefaultHttpContext(IFeatureCollection features)
        {
             Initialize(features);
        }
    }
}

没错吧,有同学可能要问了,工具箱里面的这些工具什么时候初始化的呢? 先别急,我们先看看我们熟悉的 Request 和 Response。

HttpRequest

同样在 ASP.NET Core ,HttpRequest 也成为了一个抽象类,它的默认实现叫 DefaultHttpRequest,主要是封装浏览器对服务器的请求的各种数据,包括浏览器请求的网址,查询字符串数据或表单数据等等...

不一一详细介绍了,都是很简单的内容。

HttpResponse

HttpResponse 也成为了一个抽象类,它的默认实现叫 DefaultHttpResponse,主要是是服务器接收到浏览器的请求后,处理返回结果常用的一个对象。

ASP.NET Core 管道

是时候该解释一下上面的 工具箱 初始化的问题了,我想我用一个图来直接说明管道中的请求再合适不过了,下面就是一个 ASP.NET Core 整个服务端构建管道一个流程图:

从图中可以看到,RequestDelegate 携带着 HttpContext 一路经过各种 Server、Hosting 等,最终到达了由 IApplicationBuilder 构建出来的 Application pipeline 这一管道区域,然后再经过各种中间件处理,最终构建出来了我们的 Response,而我们的工具箱 也正是在这个过程中变得 “ 饱满 ” 起来。

有一个需要知道的知识点就是,中间件是怎么样添加或者叫注册到管道中的呢? 又是如何被应用起来的呢?

上面的图可以看到,橙色区域的 Application pipeline 是由 IApplicationBuilder 构建起来的。也就是说我们可以在 IApplicationBuilder 做点什么东西来添加我们的中间件。 是的 IApplicationBuilder 暴露出来了一个 IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware); 方法来让我们注册中间件,也就是说位于 Startup.cs 文件中的 Configure 方法。

那么又是怎么样应用起来的呢? IApplicationBuilder 在 Hosting 中有一个 IApplicationBuilderFactory 的对象,Hosting 通过这个Factory 创建之后就会传递到了 HostingApplication 对象中,最后由 IWebHost 对象调用 IServer 对象的Start 同时把 HostingApplication传递进去来最终启动服务端。可以对照上面的图理解一下。

总结

在本篇中,我们知道了 ASP.NET Core Http 管道中的几个对象,他们分别是 IApplicationBuilder , RequestDelegate , HttpContext , HttpRequest , HttpResponseIFeatureCollection 等,然后也知道了他们之间的关系,接着我们通过一个管道流程图知道了他们的调用关系,也知道了如何向管道中注册中间件。

时间: 2024-10-24 05:17:27

NET Core HTTP 管道的相关文章

ASP.NET Core HTTP 管道中的那些事儿

IApplicationBuilder IApplicationBuilder 是应用大家最熟悉它的地方应该就是位于 Startup.cs 文件中的 Configure 方法了吧 public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory){     app.UseDeveloperExceptionPage();     app.UseStaticFiles();     app.UseMvc(); }

ASP.NET Core真实管道详解[2]:Server是如何完成针对请求的监听、接收与响应的【上】

Server是ASP .NET Core管道的第一个节点,负责完整请求的监听和接收,最终对请求的响应同样也由它完成.Server是我们对所有实现了IServer接口的所有类型以及对应对象的统称,如下面的代码片段所示,这个接口具有一个只读属性Features返回描述自身特性集合的FeatureCollection对象,另一个Start方法用于启动服务器. 1: public interface IServer : IDisposable 2: { 3: IFeatureCollection Fea

ASP.NET Core真实管道详解[1]

ASP.NET Core管道虽然在结构组成上显得非常简单,但是在具体实现上却涉及到太多的对象,所以我们在 <ASP.NET Core管道深度剖析[共4篇]> 中围绕着一个经过极度简化的模拟管道讲述了真实管道构建的方式以及处理HTTP请求的流程.在这个系列 中,我们会还原构建模拟管道时刻意舍弃和改写的部分,想读者朋友们呈现一个真是的HTTP请求处理管道. ASP.NET Core 的请求处理管道由一个Server和一组有序排列的中间件构成,前者仅仅完成基本的请求监听.接收和响应的工作,请求接收之

ASP.NET Core真实管道详解[1]:中间件是个什么东西?

ASP.NET Core管道虽然在结构组成上显得非常简单,但是在具体实现上却涉及到太多的对象,所以我们在 <ASP.NET Core管道深度剖析[共4篇]> 中围绕着一个经过极度简化的模拟管道讲述了真实管道构建的方式以及处理HTTP请求的流程.在这个系列 中,我们会还原构建模拟管道时刻意舍弃和改写的部分,想读者朋友们呈现一个真是的HTTP请求处理管道. ASP.NET Core 的请求处理管道由一个Server和一组有序排列的中间件构成,前者仅仅完成基本的请求监听.接收和响应的工作,请求接收之

如果你想深刻理解ASP.NET Core请求处理管道,可以试着写一个自定义的Server

我们在上面对ASP.NET Core默认提供的具有跨平台能力的KestrelServer进行了详细介绍(<聊聊ASP.NET Core默认提供的这个跨平台的服务器——KestrelServer>),为了让读者朋友们对管道中的Server具有更加深刻的认识,接下来我们采用实例演示的形式创建一个自定义的Server.这个自定义的Server直接利用HttpListener来完成针对请求的监听.接收和响应,我们将其命名为HttpListenerServer.在正式介绍HttpListenerServ

.NET Core 请求管道

节选自这里 HTTP协议自身的特性决定了任何一个Web应用的工作方式都是监听.接收并处理HTTP请求,并在最终对请求予以响应,HTTP请求处理是管道式设计典型的应用场景.我们根据HTTP请求的处理流程定制出一个消息处理管道,让接收到的HTTP请求消息想水一样流入这个管道,组成这个管道的各个环节一次对它作相应的处理.处理的结果同样转变成消息逆向流入这个管道进行处理,并最终转变成回复给客户端的HTTP响应. HTTP请求处理流程始于对请求的监听与接收,终于对请求的响应,这两项工作由同一个对象来完成,

ASP.NET Core管道深度剖析(4):管道是如何建立起来的?

小分享:我有几张阿里云优惠券,用券购买或者升级阿里云相应产品最多可以优惠五折!领券地址:https://promotion.aliyun.com/ntms/act/ambassador/sharetouser.html?userCode=ohmepe03 在<管道是如何处理HTTP请求的?>中,我们对ASP.NET Core的请求处理管道的构成以及它对请求的处理流程进行了详细介绍,接下来我们需要了解的是这样一个管道是如何被构建起来的.这样一个管道由一个服务器和一个HttpApplication

ASP.NET Core管道深度剖析(3):管道是如何处理HTTP请求的?

我们知道ASP.NET Core请求处理管道由一个服务器和一组有序的中间件组成,所以从总体设计来讲是非常简单的,但是就具体的实现来说,由于其中涉及很多对象的交互,我想很少人能够地把它弄清楚.为了让读者朋友们能够更加容易地理解管道处理HTTP请求的总体流程,我们根据真实管道的实现原理再造了一个“模拟管道”并在此管道上开发了一个发布图片的应用,这篇文章旨在为你讲述管道是如何处理HTTP请求的 目录一.HttpApplication    FeatureCollection    HostingApp

ASP.NET Core管道深度剖析[共4篇]

之所以称ASP.NET Core是一个Web开发平台,源于它具有一个极具扩展性的请求处理管道,我们可以通过这个管道的定制来满足各种场景下的HTTP处理需求.ASP. NET Core应用的很多特性,比如路由.认证.会话.缓存等,也同时定制消息处理管道来实现的.我们甚至可以通过管道定制在ASP.NET Core平台上创建我们自己的Web框架,实际上MVC和SingalR这两个重要的Web框架也是采用这样的方式创建的. 一.采用管道处理HTTP请求 HTTP协议自身的特性决定了任何一个Web应用的工