当前位置:   article > 正文

golang 框架_HTTP中间件机制实现与原理 - 从零开始写GO-API框架 [重复造轮子 - Golang]...

golang 从零搭建api框架

大家好,很高兴您能阅读这篇文章。

最近在投稿公众号时发现从未做过自我介绍,首先请允许我介绍一下自己。

我叫张晓亮,就职于新浪微博,Golang的忠实粉丝,平时的爱好看看书、撸撸码,典型的程序员性格,最近喜欢上写博客,发现不仅能从中了解到很多细节,也能帮助到其他人。

引言

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

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

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

你可以使用中间件做什么?

  1. 1、重置HTTP请求路由
  2. 2、统一安全限制、信息上报
  3. 3、Header操作、http请求认证
  4. 4、屏蔽爬虫
  5. 5、提供调试信息
  6. 6、请求日志记录
  7. 还有很多,可以自行发掘下

f75f18c6463e7f3342a6b284e7f22518.png

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

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

http中间件使用案例

惯例我们来看使用中间件的案例:

测试代码

  1. func middlewareLoger() koala.HandlerFunc {
  2. return func(ctx *koala.Context) {
  3. fmt.Printf("%+v", ctx.Req)
  4. fmt.Println("middloger 中间件")
  5. // fmt.Printf("%+V 进入到中间件了n", ctx)
  6. }
  7. }
  8. func main() {
  9. app := koala.New()
  10. app.Use(middlewareLoger())
  11. app.Add("GET", "/profile/xiaoliang", func(ctx *koala.Context) {
  12. ctx.Text("profile.xiaoliang")
  13. })
  14. }

web请求地址:http://127.0.0.1:8080/profile/xiaoliang1 输出

  1. [KOALA-DEBUG][启动中]
  2. Add GET /profile/xiaoliang
  3. Add GET /profile/xiaoliang1
  4. Add GET /member/:id
  5. [KOALA-DEBUG]监听端口[:8080]
  6. [KOALA-DEBUG][服务启动成功]
  7. 此处是中间件输出信息
  8. &{Method:GET URL:/profile/xiaoliang1 Proto:HTTP/1.1 ...... ctx:0xc00005c4c0}middlewareLoger 中间件

实现扩展HTTP中间件机制

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

先来看张图

f3fc3cc2005f1d67fafd233bd8d20e88.png

可以看看,如果我们把路由函数xiaoliang看做汉堡里的肉饼,中间件函数看成面包,那么middlewareLoger包住了肉饼。

这里可以实现很多层的中间件,为了实现简单,我们这里就做一层。

撸代码

准备工作完成,我们开始撸代码吧。我比较喜欢这个环节^_^.

以下代码逻辑,是按照实现先后顺序展示

代码位置:https://github.com/zl8762385/koala/blob/master/v1/koala.go

  1. type Middleware interface {}
  2. // 定义 koala引擎结构
  3. type Koala struct {
  4. ...代码折叠
  5. // 中间件
  6. middleware []HandlerFunc
  7. }
  8. // 注册中间件
  9. func(k *Koala) Use(m ...Middleware) {
  10. for i := range m {
  11. if m[i] != nil {
  12. // 注册中间件放入切片数组
  13. k.middleware = append(k.middleware, warpMiddleware(m[i]))
  14. }
  15. }
  16. }

处理不同中间件类型,在这里我们就很容易扩展HTTP中间件机制了

目前仅实现request,后续会陆续扩展

  1. func warpMiddleware(m Middleware) HandlerFunc {
  2. // 断言当前函数类型
  3. switch m:= m.(type) {
  4. case HandlerFunc:
  5. return m
  6. case func (*Context):
  7. return m
  8. default:
  9. fmt.Printf("%+V", m)
  10. panic("没找到相关中间件")
  11. }
  12. }

next.ServHTTP中间件用户态实现

  1. // 实现net/http 需要的servehttp服务
  2. func (k *Koala) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
  3. ...代码折叠
  4. // 执行相关操作
  5. ctx.Next()
  6. ...代码折叠
  7. }

代码位置:https://github.com/zl8762385/koala/blob/master/v1/context.go

  1. // 首先处理中间件,然后处理路由句柄
  2. func (c *Context) Next() {
  3. // http中间件处理
  4. c.middleware()
  5. // 路由映射处理
  6. c.koala.router().HandlerRouter(c)
  7. }
  8. // 执行HTTP中间件
  9. func (c *Context) middleware() {
  10. for m := range c.koala.middleware{
  11. // c http上下文传递给注册的中间件函数,这时候已经拿到了用户侧web请求数据,可以进行响应的逻辑操作
  12. c.koala.middleware[m](c)
  13. }
  14. }

晓亮嘚吧嘚,请听下回分解

看到这里大伙也发现中间件代码部分实际上不复杂,复杂是一些概念上的知识。

作者原是phper,对于中间件的了解基本属于黑洞。所以这章基础知识讲解的多了一些,一自己巩固知识点,二让看文章的您也可以跟着我的节奏复习一下。

文章还会陆续更新,最近在研究数据库连接池相关知识,准备利用这个框架的轮廓,我们在写一个关于连接池相关的包。

作者本人golang相关知识有限,如讲解不正确,还希望大牛们能帮忙指正,晓亮先感谢您~

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号