Write the Code. Change the World.

11月 23

无论是在前端语言,还是后端语言,中间件的实现是一个很好的设计。比如 vue 中的拦截器,又比如 laravel 中的中间件。都是好东西。go 中也有中间件的实现,iris 中也有对应的封装。

举一个比较现实的例子。post 请求发送数据,以及返回的数据,通过控制台,在 network 中可以看的到(抓包也可以)。如果你在请求之前,先进行加密了。发送的数据就不知道了吗(用户看的见是什么,却不知道代表着什么)。

用户不知道,服务端同样不知道,因为前端数据进行了加密(前端数据加密没有保证,至少保证了眼睛看到的,至于有精力深究,终究会还原回来)。这个时候,服务端就需要对数据进行解密。解密好了后,服务端会进行对应的处理,然后返回数据给前端。返回的数据,如果不加密,用户也是会看的到数据代表的啥。所以,在返回数据之前,服务端需要对数据也进行加密。

加解密可以有 aes 这些。这里不是重点,重点的是这个环节要处理的事情。因为加解密对现实的逻辑并没有实在的用处。这个时候,中间件的作用就体现出来了。中间件分前置中间件和后置中间件。

在前置中间件中,我们对数据进行解密。在后置中间件中,对数据进行加密。而中间件,是一个单独存在的逻辑,和项目功能逻辑是独立开来的。如果有一天,你不想要这个加解密,只需要去掉这个中间件或修改中间件逻辑即可。

在 larvel 中,前置中间件,后置中间件可以同时存在一个类中,特方便。 go 我也刚学,不是很熟悉。go 使用 UseDone 这两个方法来添加前置中间件和后置中间件。或函数中,具体的参数位置来提现。

中间件往往和路由分不开的。这样,中间件又会有全局中间件和局部中间件,提现在你用在什么地方。比如,你对所有的路由使用中间件,只需要对 iris 使用中间件,如果想对某个路由分组或某个路由使用,就在具体的路由中使用即可。后边会具体的以简单 demo 的方式列出来。

出现中间件的时候

全局

在前置中间件中,还在 头部设置了一个值, begin。

func main() {
    app := iris.New()
    app.Use(begin)
    app.Done(end)
    …   
}

func begin(ctx iris.Context) {
    t := time.Now().UnixNano()
    str := strconv.FormatInt(t, 10)
    fmt.Printf("begin %s \n\n", str)
    ctx.Request().Header.Set("begin", str)
    ctx.Next()
}

func end(ctx iris.Context) {
    t := time.Now().UnixNano()
    str := ctx.GetHeader("begin")
    t1, _ := strconv.ParseInt(str, 10, 64)
    elapse := t - t1
    fmt.Printf("end url:%s 耗时 %dns\n\n", ctx.Path(), elapse)
    ctx.Next()
}

记住, Next()方法一定要执行。如果在哪个中间件中没执行,就会卡在某个中间件中了。

路由分组

通常路由分组中会做跨域,用户认证等行为。mvc.Application 对象的 Router 一样可以进行 Use 和 Done 来作为前置后置中间件。

package main

import (
    "favor/routes"
    "fmt"
    "strconv"
    "time"

    "github.com/iris-contrib/middleware/cors"
    "github.com/kataras/iris/v12"
    "github.com/kataras/iris/v12/mvc"
)

func main() {
    app := iris.New()

    crs := cors.New(cors.Options{
        AllowedOrigins:   []string{"*"},
        AllowCredentials: true,
    })

    mvc.Configure(app.Party("/api", crs), routes.RegisterApiRoutes)
    mvc.Configure(app.Party("/", partyMiddleware), routes.RegisterWebRoutes)
    app.Run(iris.Addr(":80"))
}

func partyMiddleware(ctx iris.Context) {
    fmt.Println("this is party middleware")
    ctx.Next()
}

# routes/web.go
package routes

import (
    "favor/app/http/controllers/web"

    "github.com/kataras/iris/v12"
    "github.com/kataras/iris/v12/mvc"
)

func RegisterWebRoutes(app *mvc.Application) {
    app.Router.Use(func(ctx iris.Context) {
        ctx.Application().Logger().Infof("Web Path: %s \n\n", ctx.Path())
        ctx.Next()
    })

    app.Router.Done(func(ctx iris.Context) {
        ctx.Application().Logger().Infof("Web Over: %s \n\n", ctx.Path())
        ctx.Next()
    })

    app.Party("/user").Handle(new(web.UserController))
}

具体路由中

package api

import (
    . "fmt"

    "github.com/kataras/iris/v12"
    "github.com/kataras/iris/v12/mvc"
)

type UserController struct {
}

func (c *UserController) BeforeActivation(b mvc.BeforeActivation) {
    Println("BeforeActivation")
    b.Handle("GET", "/permissions", "GetPermissions", permissionMiddleware)
}

…
func permissionMiddleware(ctx iris.Context) {
    Println("permissionMiddleware")
    ctx.Next()
}

相关文章

官方 mvc 实例:
https://github.com/kataras/iris/tree/master/_examples/mvc/overview

https://www.jianshu.com/p/e45fa112bf4d

https://www.cnblogs.com/liyutian/p/10270935.html

发表评论

电子邮件地址不会被公开。 必填项已用*标注