无论是在前端语言,还是后端语言,中间件的实现是一个很好的设计。比如 vue 中的拦截器,又比如 laravel 中的中间件。都是好东西。go 中也有中间件的实现,iris 中也有对应的封装。
举一个比较现实的例子。post 请求发送数据,以及返回的数据,通过控制台,在 network 中可以看的到(抓包也可以)。如果你在请求之前,先进行加密了。发送的数据就不知道了吗(用户看的见是什么,却不知道代表着什么)。
用户不知道,服务端同样不知道,因为前端数据进行了加密(前端数据加密没有保证,至少保证了眼睛看到的,至于有精力深究,终究会还原回来)。这个时候,服务端就需要对数据进行解密。解密好了后,服务端会进行对应的处理,然后返回数据给前端。返回的数据,如果不加密,用户也是会看的到数据代表的啥。所以,在返回数据之前,服务端需要对数据也进行加密。
加解密可以有 aes 这些。这里不是重点,重点的是这个环节要处理的事情。因为加解密对现实的逻辑并没有实在的用处。这个时候,中间件的作用就体现出来了。中间件分前置中间件和后置中间件。
在前置中间件中,我们对数据进行解密。在后置中间件中,对数据进行加密。而中间件,是一个单独存在的逻辑,和项目功能逻辑是独立开来的。如果有一天,你不想要这个加解密,只需要去掉这个中间件或修改中间件逻辑即可。
在 larvel 中,前置中间件,后置中间件可以同时存在一个类中,特方便。 go 我也刚学,不是很熟悉。go 使用 Use 和 Done 这两个方法来添加前置中间件和后置中间件。或函数中,具体的参数位置来提现。
中间件往往和路由分不开的。这样,中间件又会有全局中间件和局部中间件,提现在你用在什么地方。比如,你对所有的路由使用中间件,只需要对 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