HttpServer 模块
1️⃣ 概述
在 sylar 框架中,HttpServer 是 TcpServer 的核心派生类,也是整个框架在 Web 开发领域的直接入口。如果说 TcpServer 负责的是 底层 的 “连接管理”,那么 HttpServer 负责的就是 “业务协议生命周期的全链路治理”。
HttpServer 不仅继承了 TcpServer 高并发、协程驱动 的优良基因,还引入了现代 Web 框架必备的 SSL 安全通信、中间件插件化、**Session 状态管理** 以及 Servlet 路由分发 等高级特性。
2️⃣ 设计核心
HttpServer 的 核心逻辑 高度凝练在重写的 handleClient 方法中。
handleClient将socket接收到的Http请求 转化成最终的HTTP响应,这其中经历了一套标准化的 “流水线” 操作:
- 安全加固 (
SSL/TLS): 识别连接属性。若是HTTPS请求,则在最前端完成 非对称加密握手 逻辑(doHandShake),确保后续数据在加密流(SslSocketStream)中传输。 - 状态化封装
Session: 将原始socket包装为HttpSession,通过 流式接口 屏蔽底层读写细节,实现对HTTP请求报文的自动化解析。 - 拦截与增强 (
Middleware): 通过MiddleChain机制,在业务逻辑执行前后嵌入中间件。无论是跨域处理(CORS)、日志审计还是身份验证,都能以 非侵入 的方式接入。 - 业务路由 (
Servlet Dispatch): 根据请求的URI,通过ServletDispatch精确匹配对应的业务处理器(Servlet),实现 “一对一” 的逻辑分发。
3️⃣ 相关组件
1️⃣ httpSession
HttpSession 类可以理解成 “一次 HTTP 连接的会话封装”:
- 把底层
socket流(SocketStream) 包装起来:提供 收请求、发响应、关闭连接 这三个最核心的HTTP服务端操作,让上层业务不需要直接跟socket打交道。 HttpSession不关心底层是TCP还是SSL,它只依赖 “流” 的读写能力。
整体框架
1 | class HttpSession |
1 | HttpSession::HttpSession(SocketStream::ptr stream, bool owner) |
m_stream:保存socket连接通。SocketStream类保存了从socket读/写能力。recvRequest():从字节流SocketStream读出一个完整的Http请求。sendResponse():它会把HttpResponse变成标准HTTP响应文本并写入socket,并将其发送给客户端。close():关闭socket的读写能力
2️⃣ SSL 相关成员
SslConfig
HttpServer 迈向生产环境的过程中,安全通信 HTTPS 是无法绕过的门槛。SslConfig 类是简单的配置集合,但它实际上是服务器 “安全策略的蓝图”。
ssl_config主要提供各个成员变量的set/get方法。
成员变量
m_certfile: 存放服务器的公钥证书。通常是.crt或.pem格式在握手阶段发送给客户端,包含服务器的名称、公钥以及 CA 的签名。它是客户端验证服务器合法性的“身份证”。
m_keyfile: 存放服务器的私钥。通常是.key或.pem格式)。用于解密客户端发送的对称密钥,或在握手时进行数字签名。
m_chainfile: 存放中间CA(证书颁发机构)的证书。如果 服务器证书 不是直接由 顶级根证书 签发的,客户端需要通过 证书链 追溯到它信任的根证书。
m_version: 指定使用的TLS版本。主要用于 控制安全上下限。例如,
TLS 1.3移除了许多不安全的加密算法并优化了握手时间。通常建议使用TLS_1_2或更高。m_cipherList: 定义服务器支持的一系列 加密算法。规定双方如何交换密钥、如何加密数据、如何校验完整性。
m_verifyClient: 是否开启双向认证 (mTLS) 开关。开启后,服务器在握手时会强制要求客户端提供证书。常用于银行、
API网关或微服务间内部通信。m_verifyDepth: 证书链校验的最大深度。例如设为 4,表示服务器在验证客户端证书时,最多往上追溯 4 级 CA。超过此深度则视为无效,防止通过过长的证书链进行伪造攻击。
m_sessionTimeout:SSL Session缓存的有效期(单位:秒)。客户端在有效期内重连时,可以跳过繁琐的非对称加密握手,直接恢复之前的会话,大幅降低
CPU负载。m_sessionCacheSize: 服务器内存中存储SSL会话信息的最大条数。限制缓存占用的内存。对于超大规模并发的服务器,需要增大此值以提高会话复用率,减少频繁的完整握手。
SslContext
在 sylar 框架中,SslContext 扮演的是 OpenSSL 资源的掌门人。
它的核心意义在于将 “复杂的 C API 过程式初始化” 封装为 “简洁的 C++ 面向对象调用”。在整个系统中,它的作用可以概括为以下三点:
- 资源生命周期管理: 通过
Noncopyable和析构函数中的SSL_CTX_free,确保底层的安全上下文资源永不泄漏,且不被非法拷贝。 - 安全策略落地的“处理器”: 读取
SslConfig中的静态配置(证书路径、协议版本、加密套件),并将其 “翻译” 为OpenSSL内部的状态机参数。 - 握手模板的“母体”: 在
HttpServer中,每当有一个新的TCP连接进来,系统都会引用这个唯一的SslContext句柄来产生具体的SSL握手对象。
重要函数
构造函数
保存 SSL 配置以及初始化SSL_CTX* m_ctx为空1
2
3
4SslContext::SslContext(const SslConfig& config)
: m_config(config)
, m_ctx(nullptr)
{}initilaize()
作用:把服务器端TLS/SSL所需要的OpenSSL环境和SSL_CTX(上下文)一次性初始化好,让后续每个连接都能基于这个上下文去创建SSL*并完成握手、加密通信。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31bool SslContext::initilaize()
{
// 初始化OpenSSL
OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, nullptr);
// 创建 SSL 上下文
const SSL_METHOD* method = TLS_server_method();
m_ctx = SSL_CTX_new(method);
if (!m_ctx)
{
handleSslError("Failed to create SSL context");
return false;
}
// 设置Ssl选项
long option = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION |SSL_OP_CIPHER_SERVER_PREFERENCE;
SSL_CTX_set_options(m_ctx, option);
// 加载证书和密钥
if (!loadCertificates())
{
return false;
}
// 设置协议版本
if (!setupProtocol())
{
return false;
}
// 设置会话缓存
setupSessionCache();
// 表示成功输出
SYLAR_LOG_INFO(g_logger) << "SSL context initialized successfully";
return true;
}loadCertificates():主要用来加载公钥证书、加载私钥、验证公钥证书和私钥匹配、构建完整的“证书链” 以供客户端验证。setupProtocol():设置支持的TLS的版本,以及加密套件。setupSessionCache:设置会话超时时间,确保客户端在会话期间断开重连可以无需重复握手。
SslSocketStream
SslSocketStream 继承自 SocketStream,它的核心使命是:在不改变上层逻辑的前提下,透明地为数据流进行 加密传输。
1 | class SslSocketStream : public SocketStream |
