在 .NET Core 中,请求处理管道是一个中间件(Middleware)链,用于处理 HTTP 请求并生成响应。管道的底层实现基于 Microsoft.AspNetCore.Http 命名空间中的一些核心类和接口

1. 核心组件

1.1 HttpContext

  • HttpContext 是 HTTP 请求和响应的核心抽象,封装了请求信息(如请求头、请求体、查询参数等)和响应信息(如状态码、响应头、响应体等)。
  • • 每个请求都会创建一个 HttpContext 实例,并在整个管道中传递。

1.2 HttpRequestHttpResponse

  • HttpRequestHttpResponse 分别表示 HTTP 请求和响应,是 HttpContext 的一部分。
  • HttpRequest 包含请求的详细信息,如路径、方法、头、体等。
  • HttpResponse 用于设置响应的状态码、头、体等。

1.3 RequestDelegate

  • RequestDelegate 是一个委托,表示处理 HTTP 请求的方法:
public delegate Task RequestDelegate(HttpContext context);
  • • 管道中的每个中间件都是一个 RequestDelegate

1.4 Middleware

  • • 中间件是一个类或方法,用于处理请求并调用管道中的下一个中间件。
  • • 中间件通常通过 UseRun 方法注册到管道中。

2. 定义 ApplicationBuilder 接口

首先,我们定义 IApplicationBuilder 接口:

public interface IApplicationBuilder
{
    // 添加中间件到管道中
    IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware);     // 构建最终的请求处理管道
    RequestDelegate Build();     // 获取或设置应用程序服务提供者
    IServiceProvider ApplicationServices { get; set; }     // 获取属性字典,用于存储共享数据
    IDictionary<string, object> Properties { get; }
}

3. 定义 RequestDelegate 委托

管道的核心是基于委托(Delegate)和上下文(Context)的机制。

**RequestDelegate**:是一个表示处理 HTTP 请求的委托。

public delegate Task RequestDelegate(HttpContext context);
  • **HttpContext**:封装了 HTTP 请求和响应的所有信息,包括请求头、请求体、响应头、响应体等。

每个中间件本质上是一个 RequestDelegate,它接收 HttpContext 并处理请求,同时可以选择调用下一个中间件。


4. 实现 ApplicationBuilder

接下来,我们实现 ApplicationBuilder 类:

public class ApplicationBuilder : IApplicationBuilder
{
    // 存储中间件组件的列表
    private readonly IList<Func<RequestDelegate, RequestDelegate>> _components = new List<Func<RequestDelegate, RequestDelegate>>();     // 获取或设置应用程序服务提供者
    public IServiceProvider ApplicationServices { get; set; }     // 获取属性字典,用于存储共享数据
    public IDictionary<string, object> Properties { get; } = new Dictionary<string, object>();     // 添加中间件到管道中
    public IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware)
    {
        _components.Add(middleware);
        return this;
    }     // 构建最终的请求处理管道
    public RequestDelegate Build()
    {
        // 默认的请求处理程序,返回 404 状态码
        RequestDelegate app = context =>
        {
            context.Response.StatusCode = 404;
            return Task.CompletedTask;
        };         // 反向遍历中间件组件列表,构建嵌套的请求处理管道
        foreach (var component in _components.Reverse())
        {
            app = component(app);
        }         return app;
    }
}

5. 创建中间件

我们创建一个简单的日志收集中间件来展示如何使用 **ApplicationBuilder**

public class CustomizeMiddleware
{
    private readonly RequestDelegate _next;     // 构造函数,接受下一个中间件的委托
    public CustomizeMiddleware(RequestDelegate next)
    {
        _next = next;
    }     // 中间件的请求处理方法
    public async Task Invoke(HttpContext context)
    {
        Console.WriteLine("自定义中间件: Before");
        await _next(context); // 调用下一个中间件
        Console.WriteLine("自定义中间件: After");
    }
}

6. 使用 ApplicationBuilder 构建管道

public class Program
{
    public static void Main(string[] args)
    {
        // 创建 ApplicationBuilder 实例
        var builder = new ApplicationBuilder();         // 添加 CustomizeMiddleware 到管道中
        builder.Use(next => new CustomizeMiddleware(next).Invoke);         // 添加内联中间件到管道中
        builder.Use(next => async context =>
        {
            Console.WriteLine("内联中间件: Before");
            await next(context); // 调用下一个中间件
            Console.WriteLine("内联中间件: After");
        });         // 构建最终的请求处理管道
        var app = builder.Build();         // 创建一个 HttpContext 实例
        var context = new DefaultHttpContext();         // 执行管道
        app(context).Wait();
    }
}

输入结果为:


7.总结

.NET Core 管道的底层实现是基于委托链的机制,每个中间件都是一个 RequestDelegate,通过链式调用来处理 HTTP 请求和响应。管道的构建过程通过 IApplicationBuilder 接口完成,中间件的添加顺序决定了管道的执行顺序。通过理解管道的底层实现,可以更好地掌握 .NET Core 的请求处理机制,并能够灵活地配置和扩展管道。

.Net Core 管道底层源码实现的更多相关文章

  1. AspNetCore底层源码剖析(三)IOC

    title: AspNetCore底层源码剖析(三)IOC date: 2022-09-21 13:20:01 categories: 后端 tags: - .NET 介绍 每个 ASP.NET Co ...

  2. Android开发之漫漫长途 Ⅵ——图解Android事件分发机制(深入底层源码)

    该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...

  3. 为什么很多类甚者底层源码要implements Serializable ?

    为什么很多类甚者底层源码要implements Serializable ? 在碰到异常类RuntimeException时,发现Throwable实现了 Serializable,还有我们平进的ja ...

  4. List-LinkedList、set集合基础增强底层源码分析

    List-LinkedList 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] 继上一章继续讲解,上章内容: List-ArreyLlist集合基础增强底层源码分析:https:// ...

  5. List-ArrayList集合基础增强底层源码分析

    List集合基础增强底层源码分析 作者:Stanley 罗昊 [转载请注明出处和署名,谢谢!] 集合分为三个系列,分别为:List.set.map List系列 特点:元素有序可重复 有序指的是元素的 ...

  6. 从底层源码浅析Mybatis的SqlSessionFactory初始化过程

    目录 搭建源码环境 POM依赖 测试SQL Mybatis全局配置文件 UserMapper接口 UserMapper配置 User实体 Main方法 快速进入Debug跟踪 源码分析准备 源码分析 ...

  7. Java泛型底层源码解析-ArrayList,LinkedList,HashSet和HashMap

    声明:以下源代码使用的都是基于JDK1.8_112版本 1. ArrayList源码解析 <1. 集合中存放的依然是对象的引用而不是对象本身,且无法放置原生数据类型,我们需要使用原生数据类型的包 ...

  8. 2018.11.20 Struts2中对结果处理方式分析&struts2内置的方式底层源码剖析

    介绍一下struts2内置帮我们封装好的处理结果方式也就是底层源码分析 这是我们的jar包里面找的位置目录 打开往下拉看到result-type节点 name那一列就是我们的type类型取值 上一篇博 ...

  9. 全方位深度剖析PHP7底层源码(已完结)

    第1章 课程介绍本章主要介绍课程要讲的知识点,以及课程要求等. 第2章 PHP7的新特性本章主要介绍PHP7的新特性,做基准测试,与PHP5对比验证PHP7的性能提升程度,引出对PHP7源码学习的必要 ...

  10. BAT资深工程师 由浅入深分析 Tp5&Tp6底层源码 - 分享

    BAT资深工程师由浅入深分析Tp5&Tp6底层源码 第1章 课程简介 本章主要让大家知道本套课程的主线, 导学内容,如何学习源码等,看完本章要让小伙伴觉得这个是必须要掌握的,并且对加薪有很大的 ...

随机推荐

  1. 学习JavaScript第四天

    文章目录 1 回顾 内置对象 2 内置对象 2.1 Function 2.2 Global 3 DOM 部分知识点介绍 4 BOM 4.1 window ① 弹框 ② 打开关闭窗口 ③ 页面滚动 ④ ...

  2. Spire.Pdf打印PDF文件

    1 /// <summary> 2 /// Spire.Pdf打印PDF文件 3 /// </summary> 4 /// <param name="fileN ...

  3. 用文字“画出”时序图:用 AI+Mermaid.js 解决交互过程中的问题

    什么是时序图 序列图是一种用于描述对象之间在时间上的交互顺序的图表. 它可以展示对象之间是如何相互作用的,以及这些交互的顺序. 什么是Mermaid Mermaid.js是一个开源项目,它允许你通过简 ...

  4. .NET 9 中没有 wasi 实验性支持

    2023年10月份写个一篇<本计划在 .NET 8 中推出的 WASI 推迟到 .NET 9>[1],根据此问题,在 .NET 9 RTM 中似乎不会有wasi-experimental, ...

  5. Spring AI 再更新:如何借助全局参数实现智能数据库操作与个性化待办管理

    引言 好的,今天我们继续聊一下Spring AI的相关内容.在10月的时候,我使用Spring AI搭建了一个简易版的个人助理系统,整体来说效果还是非常不错的.通过这次尝试,我对业务系统与AI结合的探 ...

  6. 如何使用Python编写一个Lisp解释器

    原文出处: Peter Norvig   译文出处: jnjc(@jnjcc) 本文有两个目的: 一是讲述实现计算机语言解释器的通用方法,另外一点,着重展示如何使用Python来实现Lisp方言Sch ...

  7. Python数据存储之shelve和dbm

    一.shelve 和 dbm 的介绍 shelve 和 dbm 都是 python 自带的数据库管理模块,可以用于持久化存储和检索 python 中的对象. 虽然这两个模块的本质都是建立 key-va ...

  8. 服务器安全之DenyHosts

    情景:今天登录服务器,突然发现登录之后展示的信息有点多,仔细端倪发现: There were 3975 failed login attempts since the last successful ...

  9. java/spring项目打成jar包供第三方引用方案

    分类 单独工具类 比如StringUtils 注入类工具类 实现 单独工具类 将项目打jar包 项目结构 开始打包: 在目标项目中pom引用直接使用 注入类工具类 当我们想要利用SpringBoot封 ...

  10. Sealos Devbox 基础教程:使用 Cursor 从零开发一个完整的项目

    作者:熊猫Jay,上市公司技术负责人,破局AI 提示词.AI编程教练.通往AGI之路内容共创者 最近发现身边越来越多人尝试用 Cursor 写代码.开发小产品了. 如果想要实现商业化或引流,我们的小工 ...