HTTP中间件机制实现与原理 - 从零开始写GO-API框架

Posted 跳动的代码

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HTTP中间件机制实现与原理 - 从零开始写GO-API框架相关的知识,希望对你有一定的参考价值。

引言

因golang内置的net/http天生就支持http中间件机制,所以即使不使用开源web框架,我们也可以写出扩展性很好的应用。

一个好的中间件有一个责任就是可插拔并且自足,这就意味着你可以在接口级别嵌入你的中间件他就能直接运行,且不会影响你的编码方式,这不是框架,仅仅是在请求处理里面的一层而已。

可以想象每一个中间件都是一层洋葱皮,其中每一个中间件都可以改变请求响应,我们可以很自然的把不同的逻辑放到不同的洋葱皮里,让代码更符合单一原则。

你可以使用中间件做什么?
 
   
   
 
1、重置HTTP请求路由
2、统一安全限制、信息上报
3、Header操作、http请求认证
4、屏蔽爬虫
5、提供调试信息
6、请求日志记录


还有很多,可以自行发掘下


中间件通常会是一小段代码,它可以接受一个请求,对其进行处理,每个中间件只处理一件事,完成后将其传递给下一层或最终处理。这样就做到了程序的解耦。

如果没有中间件我们必须在最终处理程序中来完成这个逻辑操作,这无疑会造成你现有业务逻辑的臃肿和代码复用率不高的问题。

http中间件使用案例

惯例我们来看使用中间件的案例:
测试代码
func middlewareLoger() koala.HandlerFunc { return func(ctx *koala.Context) {
fmt.Printf("%+v", ctx.Req) fmt.Println("middloger 中间件") // fmt.Printf("%+V 进入到中间件了\n", ctx) }}
func main() { app := koala.New() app.Use(middlewareLoger()) app.Add("GET", "/profile/xiaoliang", func(ctx *koala.Context) { ctx.Text("profile.xiaoliang") })}
web请求地址:127.0.0.1:8080/profile/ 输出
 
   
   
 
[KOALA-DEBUG][启动中]
Add GET /profile/xiaoliang
Add GET /profile/xiaoliang1
Add GET /member/:id
[KOALA-DEBUG]监听端口[:8080]
[KOALA-DEBUG][服务启动成功]

此处是中间件输出信息
&{Method:GET URL:/profile/xiaoliang1 Proto:HTTP/1.1 ...... ctx:0xc00005c4c0}middlewareLoger 中间件

实现扩展HTTP中间件机制

以上讲解了中间件的相关基础知识,也看了使用案例,下面我们来实现一下中间件是如何嵌入到web框架中,并以此来实现各种解耦的功能。
先来看张图

可以看看,如果我们把路由函数xiaoliang看做汉堡里的肉饼,中间件函数看成面包,那么middlewareLoger包住了肉饼。
这里可以实现很多层的中间件,为了实现简单,我们这里就做一层。

撸代码

准备工作完成,我们开始撸代码吧。我比较喜欢这个环节^_^.
以下代码逻辑,是按照实现先后顺序展示
代码位置: github.com/zl8762385/ko
type Middleware interface {}
// 定义 koala引擎结构type Koala struct { ...代码折叠
// 中间件 middleware []HandlerFunc
}
// 注册中间件func(k *Koala) Use(m ...Middleware) { for i := range m { if m[i] != nil { // 注册中间件放入切片数组 k.middleware = append(k.middleware, warpMiddleware(m[i])) } }}
处理不同中间件类型,在这里我们就很容易扩展HTTP中间件机制了
目前仅实现request,后续会陆续扩展
func warpMiddleware(m Middleware) HandlerFunc { // 断言当前函数类型 switch m:= m.(type) { case HandlerFunc: return m case func (*Context): return m default: fmt.Printf("%+V", m) panic("没找到相关中间件") }}
next.ServHTTP中间件用户态实现
// 实现net/http 需要的servehttp服务func (k *Koala) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
...代码折叠
// 执行相关操作 ctx.Next()
...代码折叠}
代码位置: github.com/zl8762385/ko
// 首先处理中间件,然后处理路由句柄func (c *Context) Next() { // http中间件处理 c.middleware()
// 路由映射处理 c.koala.router().HandlerRouter(c)}

// 执行HTTP中间件func (c *Context) middleware() { for m := range c.koala.middleware{ // c http上下文传递给注册的中间件函数,这时候已经拿到了用户侧web请求数据,可以进行响应的逻辑操作 c.koala.middleware[m](c) }}

鸣谢晓亮,https://www.zhihu.com/people/maoxiaoqi-1988



以上是关于HTTP中间件机制实现与原理 - 从零开始写GO-API框架的主要内容,如果未能解决你的问题,请参考以下文章

go 的路由中间件实现原理

从零开始手写 mybatismybatis interceptor 插件机制详解

从零开始学Go之容器:列表

从零开始写一个微前端框架-沙箱篇

从零开始写一个微前端框架-沙箱篇

从零开始写一个Tomcat(贰)--建立动态服务器