Skip to main content

中间件

中间件(拦截器)是在请求与响应的过程中,拦截下请求与响应并做一些操作,常见的用途是在请求前进行鉴权,在请求后对响应数据进行包装等

中间件的定义与普通路由函数一样,只是其中需要用Next()进行路由放行。

func MiddleWare(r *ghttp.Request) {
r.Middleware.Next()
}

前置中间件

在执行具体的路由函数之前进行操作的中间件称为前置中间件,例如进行登录验证的中间件:

func (s *sMiddleware) Auth(r *ghttp.Request) {
user := service.Session().GetUser(r.Context())
if user.Id == 0 {
_ = service.Session().SetNotice(r.Context(), &model.SessionNotice{
Type: consts.SessionNoticeTypeWarn,
Content: "未登录或会话已过期,请您登录后再继续",
})
// 只有GET请求才支持保存当前URL,以便后续登录后再跳转回来。
if r.Method == "GET" {
_ = service.Session().SetLoginReferer(r.Context(), r.GetUrl())
}
// 根据当前请求方式执行不同的返回数据结构
if r.IsAjaxRequest() {
response.JsonRedirectExit(r, 1, "", s.LoginUrl)
} else {
r.Response.RedirectTo(s.LoginUrl)
}
}
r.Middleware.Next()
}

后置中间件

在路由函数执行完成之后再进行操作的中间件称为后置中间件,例如对返回的数据格式进行统一封装的中间件:

// 返回处理中间件
func (s *sMiddleware) ResponseHandler(r *ghttp.Request) {
r.Middleware.Next()

// 如果已经有返回内容,那么该中间件什么也不做
if r.Response.BufferLength() > 0 {
return
}

var (
err = r.GetError()
res = r.GetHandlerResponse()
code gcode.Code = gcode.CodeOK
)
if err != nil {
code = gerror.Code(err)
if code == gcode.CodeNil {
code = gcode.CodeInternalError
}
if r.IsAjaxRequest() {
response.JsonExit(r, code.Code(), err.Error())
} else {
service.View().Render500(r.Context(), model.View{
Error: err.Error(),
})
}
} else {
if r.IsAjaxRequest() {
response.JsonExit(r, code.Code(), "", res)
} else {
// 什么都不做,业务API自行处理模板渲染的成功逻辑。
}
}
}

中件间的定义实际上就是如下:

func MiddleWare(r *ghttp.Request) {
// 前置中间件
r.Middleware.Next()
// 后置中间件
}

SetCtxVar/GetCtxVar

如果需要在一些请求流程中进行参数传递,可以用SetCtxVar/GetCtxVar进行存取

例如

func MiddleWare(r *ghttp.Request) {
r.SetCtxVar("UserName", "陆玲珑")
r.Middleware.Next()
}

在具体路由函数中取用

UserName := r.GetCtxVar("UserName")