从上面的内容我们知道ASP.NET Core请求处理管道由一个服务器和一组中间件构成,所以从总体设计来讲是非常简单的。但是就具体的实现来说,由于其中涉及很多对象的交互,很少人能够地把它弄清楚。如果想非常深刻地认识ASP.NET Core的请求处理管道,我觉得可以分两个步骤来进行:首先,我们可以在忽略具体细节的前提下搞清楚管道处理HTTP请求的总体流程;在对总体流程有了大致了解之后,我们再来补充这些刻意忽略的细节。为了让读者朋友们能够更加容易地理解管道处理HTTP请求的总体流程,我们根据真实管道的实现原理再造了一个“迷你版的管道”。[本文已经同步到《ASP.NET Core框架揭秘》之中] [源代码从这里下载]
目录
一、建立在“模拟管道”上的应用
二、HttpApplication——一组中间件的有序集合
三、HttpContext——对当前HTTP上下文的抽象
四、服务器——实现对请求的监听、接收和响应
再造的迷你管道不仅仅体现了真实管道中处理HTTP请求的流程,并且对于其中涉及的接口和类型,我们也基本上采用了相同的命名方式。但是为了避免“细枝末节”造成的干扰,我会进行最大限度的裁剪。对于大部分方法,我们只会保留最核心的逻辑。对于一些接口,我们会剔除那些与核心流程无关的成员。在通过这个模拟管道讲解HTTP请求的总体处理流程之前,我们先来看看如何在它基础上开发一个简单的应用。
我们在这个模拟管道上开发一个简单的应用来发布图片。具体的应用场景是这样:我们将图片文件保存在服务器上的某个目录下,客户端可以通过发送HTTP请求并在请求地址上指定文件名的方式来获取目标图片。如下图所示,我们利用浏览器向针对某张图片的地址(“http://localhost:3721/images/hello.png”)发送请求后,获取到的目标图片(hello.png)会直接显示到浏览器上。除此之外,如果指定的图片地址没有包含扩展名(“.png”),我们的也会帮助我们自动匹配一个文件名(不包含扩展名)相同的图片。
由于我们模拟的管道采用与真实管道一致的应用编程接口,所以两种采用的编程模式也是一致的。这个用于发布图片的应用是通过如下几行简单的代码构建起来的。如下面的代码片断所示,我们在Main方法中创建了一个WebHostBuilder对象,在调用其Build方法创建应用宿主的WebHost之前,我们调用扩展方法UseHttpListener注册了一个类型为HttpListenerServer的服务器。这个HttpListenerServer是我们自己定义的服务器,它利用一个HttpListener对象实现了针对HTTP请求的监听、接收和最终的响应。监听地址(“http://localhost:3721/images”)是通过调用扩展方法UseUrls指定的。
class Program
2: {
void Main()
4: {
new WebHostBuilder()
6: .UseHttpListener()
)
))
9: .Build()
10: .Start();
11:
12: Console.Read();
13: }
14: }