• Go中间件


    一、简述

    gin中间件类似java的拦截器,通过中间件可以在处理具体的route请求时,提前做一些业务。比如用户有效性的校验,特定日志格式的打印,错误日志的打印等等。

    一个个中间件组成一条中间件链,对HTTPRequest请求进行拦截处理,实现了代码的解耦和分离,并且中间件之间相互不用感知到,每个中间件只需要处理自己需要处理的事情即可。

    gin的中间件大致可以分为两类,全局中间件和路由中间件,下面记录gin的中间件学习过程中的一些问题。

    • 全局中间件
    • Group 中间件
    • 单个路由中间件

    二、全局中间件

    1、默认中间件

    使用router := gin.Default()定义route时,默认带了Logger()Recovery()。我们可以使用BasicAuth()中间件做一些简单的用户权限的认证

    // Default returns an Engine instance with the Logger and Recovery middleware already attached.

    func Default() *Engine {

       debugPrintWARNINGDefault()

       engine := New()

       engine.Use(Logger(), Recovery())

       return engine

    }

    gin的中间件是通过Use方法设置的,它接受一个可变的参数,所以我们可以设置多个中间件

    // Use adds middleware to the group, see example code in GitHub.

    func (group *RouterGroup) Use(middleware ...HandlerFunc) IRoutes {

       group.Handlers = append(group.Handlers, middleware...)

       return group.returnObj()

    }

    一个gin的中间件,其实就是一个HandleFunc

    router.GET("/", func(c *gin.Context) {

        c.JSON(200"首页")

    })

    后边的func(c *gin.Context) {}就是一个HandleFunc

    2、自定义中间件

    func main() {

       // 初始化环境

       initCtx, cancel := context.WithCancel(context.Background())

       defer cancel()

       //加载服务配置

       bjh.InitServicer(initCtx)

       // 默认中间件引擎

       router := gin.Default()

       router.Use(bjh.LoginAuth())

       router.GET("/", func(c *gin.Context) {

       })

       _ = router.Run(":8000")

    }

    go get gopkg.in/cas.v1

    func LoginAuth() gin.HandlerFunc {

       return func(ctx *gin.Context) {

          transCfg := &http.Transport{

             TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, // 不验证证书

          }

          client := &http.Client{Transport: transCfg}

          u, _ := url.Parse(uuap.AuthInterface)

          newClient := cas.NewClient(&cas.Options{URL: u, Client: client})

          h := newClient.HandleFunc(func(w http.ResponseWriter, r *http.Request) {

             ticket := r.FormValue("ticket")

             devtools.Log("ticket--------1", ticket)

             if ticket == "" || !cas.IsAuthenticated(r) {

                cas.RedirectToLogin(w, r)

                devtools.Log("redirect""go out")

                ctx.Abort()

                return

             }

             _, _ = fmt.Fprintf(w, "Hello %s\n", cas.Username(r))

             devtools.Log("ticket--------2", ticket)

          })

          h.ServeHTTP(ctx.Writer, ctx.Request)

          ctx.Next()

       }

    }

    示例:

    获取请求中的sessionid,写入到context中,context.Next()跳到下一个中间件中,下一个中间件会对这个session进行有效性校验(sessionid是否存在,是否过期等)

    //用户身份认证中间件

    func Validate() gin.HandlerFunc {

     return func(context *gin.Context) {

     // 参数的或者以及部分业务逻辑

     var sessionid = ""

     cookie, err := context.Request.Cookie(defs.Cookie_key)

     if err == nil && cookie != nil {

     sessionid = cookie.Value

     else {

     sessionid = session.GenerateSess(login.UserName)

     }

     context.Set("sessionid", sessionid)

     context.Next()

     return

     }

    }

    3、路由中间件

    只是针对具体的路由规则

    示例:

    下面定义了一个分组路由/user,分组路由下的/login需要验证用户名和密码,这个路由使用的是路由中间件Validate(),通过查库验证用户名和密码。而其余的路由/manager/show/manager/modify使用了路由中间件handles.Cookie(),这个中间件验证用户在登陆成功后的sessionid的有效性

    // 设置user路由组

    {

     userGroup := router.Group("/user")

     {

     //userGroup.Use(handles.AccessJsMiddleware())

     //显示用户登录主页

     userGroup.GET("/show", handles.ShowUserLogin())

     //用户登录

     userGroup.POST(

     "/login",

     handles.Validate(), //用户密码有效性验证

     handles.HandleUserLogin())

     //用户管理

     userGroup.GET("/manager/show", handles.Cookie(), handles.ShowUserManager())

     userGroup.POST("/manager/modify", handles.Cookie(), handles.HandleUserOperte())

     }

    }

    三、中间件件的流转

    gin提供了两个函数Abort()Next(),配合着return关键字用来跳转或者终止存在着业务逻辑关系的中间件。

    .Next()

    跳过当前的中间件,执行下一个中间件,待下一个中间件执行完后再回到当前next位置,执行后面的逻辑

    .Abort()

    终止该中间件的流程,如果不return的话会继续执行后面的逻辑,但不再执行其他的中间件

    结论

    1. next()函数会跳过当前中间件中next()后的逻辑,当下一个中间件执行完成后再执行剩余的逻辑

    2. abort()函数执行终止当前中间件以后的中间件执行,但是会执行当前中间件的后续逻辑

    使用 Go 处理中间件 - 知乎

    Gin框架系列03:换个姿势理解中间件 - Go语言中文网 - Golang中文社区

    golang gin 中间件,返回结果 - 漫步的影子 - 博客园

    gin使用中间件出错后不能用return终止,而应该使用Abort实现_katy的小乖的博客-CSDN博客

    使用 Go 处理中间件 - SegmentFault 思否

  • 相关阅读:
    量子笔记:多量子系统、叠加、量子计算并行处理能力
    c# 读取xml到dataset中
    1 操作系统任务调度问题----来源刘H同学
    上位机程序,上位机界面开发,ATECLOUD中国人自己的LabVIEW
    vue3前端调用后端接口实现批量删除
    ICS TRIPLEX T8310 自动化控制模块
    what is flinksql hint?
    JDK安装教程、Eclipse安装教程
    JSP session对象
    GDPU 数据结构 天码行空7
  • 原文地址:https://blog.csdn.net/spirit_8023/article/details/125999749