HTTP实用指南 | 青训营

40 阅读2分钟

HTTP框架设计

分层设计

HTTP框架采用分层设计,各层之间通过 API 通信,这样提高了代码的复用性和拓展性。

  • 应用层——提供给用户使用的接口,需要保证可理解性和简单性
  • 中间件层——对请求进行预处理和后处理
  • 路由层——为 url 请求匹配相应的Handler处理函数
  • 协议层——抽象出合适的接口,在连接上读取数据
  • 传输层——为网络I/O提供了一个可移植的接口,包括TCP/IP、UDP、域名解析和Unix域套接字

中间件

常用于日志统计,性能统计,事务处理,安全控制,异常处理

洋葱模型

2023-08-02-21-03-47-image.png

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-routervue-router而后端的koa/router也使用了这个库

gin框架则使用了前缀树这种方式来实现路由匹配

前缀树Trie

Trie用来储存可被分割为单个节点,并且可以共享前缀的数据,即树中一个节点的所有子孙都有相同的前缀

  • 每个节点只储存了一个单元

  • 节点可以被多个数据共享

  • 标记代表数据结尾的节点

  • 根据一定的路径依次通过节点可以得到特定的数据