HTTP框架设计
分层设计
HTTP框架采用分层设计,各层之间通过 API 通信,这样提高了代码的复用性和拓展性。
- 应用层——提供给用户使用的接口,需要保证可理解性和简单性
- 中间件层——对请求进行预处理和后处理
- 路由层——为 url 请求匹配相应的
Handler处理函数 - 协议层——抽象出合适的接口,在连接上读取数据
- 传输层——为网络I/O提供了一个可移植的接口,包括TCP/IP、UDP、域名解析和Unix域套接字
中间件
常用于日志统计,性能统计,事务处理,安全控制,异常处理
洋葱模型
Handler被多层中间件“包装”起来,Handler每次处理请求时都会对请求有一个预处理和后处理
处理函数的调用
Next方法保证每次调用时都会增加index,使得每次调用正确的Handler
go
复制代码
func (ctx *RequestContext) Next() {
ctx.index++
for ctx.index < int8(len(ctx.handlers)) {
ctx.handlers[ctx.index]()
ctx.index++
}
}
若是调用链中出现异常需要中止,则直接Abort方法直接将index设置为最大值
go
复制代码
func (ctx *RequestContext) Abort() {
ctx.index = IndexMax
}
路由
路由匹配一般指动态路由的匹配,即一条路由规则可以匹配某一类型而非某一条固定的路由,例如 /detail:id,可以匹配 /detail/1、/detail/2 等符合一定规则的 url
实现
前端的实现一般基于正则匹配,大多依赖依赖 path-to-regexp 这个库解析路由,例如react-router、vue-router而后端的koa/router也使用了这个库
而gin框架则使用了前缀树这种方式来实现路由匹配
前缀树Trie
Trie用来储存可被分割为单个节点,并且可以共享前缀的数据,即树中一个节点的所有子孙都有相同的前缀
-
每个节点只储存了一个单元
-
节点可以被多个数据共享
-
标记代表数据结尾的节点
-
根据一定的路径依次通过节点可以得到特定的数据