gin框架上下文中的Abort序列方法(Abort,AbortWithStatus, AbortWithStatusJSON,AbortWithError)他们都不会立刻终止当前的请求,在中间件中调用Abort方法后中间件中的后续的代码会被继续执行,但是中间件后面的handler控制器方法会被终止执行(在中间件中调用Abort以确保不会调用此请求的其余处理程序)。
gin立刻中断当前请求的2种方法
-
1. Abort + return 终止当前请求
如果需要立刻终止当前请求需要使用 Abort + return 来终止后面的代码块和后续业务逻辑的执行, 注意必须是abort序列方法+return组合才能终止带去代码的执行。
如:
if req.File == nil {
c.AbortWithStatusJSON(-1, gin.H{"msg": "请选择需要上传的文件"})
return
}
上面的c.Abort会终止gin框架继续调用后面的请求逻辑, return 会立刻终止当前代码块的执行, 必须是他们的组合才能彻底终止当前的请求,只return,他只会终止当前代码块后续代码的执行,而不会终止gin的后续处理逻辑执行。
-
2. 直接抛 panic异常
这个是golang程序中最霸道,最直接,最彻底的终止当前请求的方法!! 由于他过于霸道,所以建议大家慎用!
panic("不玩了,直接退出!")
另外还有一个os提供的函数 os.Exit(1) 这个是直接退出当前应用程序,这个大家要分清楚,不要乱用哦
中间件中使用 c.Abort()
在中间件中使用 c.Abort() 后,当前路由对应的控制器就不会被执行;
如:
有如下的路由信息
rga := r.Group("")
rga.Use(middleware.Auth) // 在rga中使用了Auth中间件
rga.POST("/file", controller.File.Upload) // 路由绑定
中间件中,如果使用了 Abort方法,则 controller.File.Upload 这个控制器就不会被执行
func Auth(c *gin.Context) {
var uid int = 0
if uid == 0 {
c.Redirect(301, "/login") // 跳转
c.Abort() // 使用了Abort
}
c.Next() // 这个会被执行
}
上面的中间件中的代码 在Abort方法后面的代码都会被执行,但是上面的路由对应的handler不会被执行; 如果我们在上面的中间件中没有使用Abort方法 , 则路由对应的handler就会被执行,这里的中间件就失效了!! 而且c.Redirect这个跳转也没用,只有使用了Abort方法后Redirect才生效。
在handler控制器中使用Abort方法
如果是在控制器handler中执行 c.Abort() , 则后面的代码会被继续执行,如果想要终止当前请求,则必须使用空 return 来终止后面的代码的执行, 如:
下面代码中我们使用了 c.AbortWithStatusJSON 方法,后面必须跟着一个空的 return, 否则后面的代码会被继续执行
func (a *cFile) Upload(c *gin.Context) {
req := &dto.InfoFileUploadReq{}
c.ShouldBind(req) //
if req.File == nil {
c.AbortWithStatusJSON(-1, gin.H{"msg": myerror.NewCode(mycode.CodeMissingParameter, "请选择需要上传的文件")})
return
}
_, err := service.InfoFileSvc().Upload(c, model.InfoFileUploadInput{
File: req.File,
RandomName: true,
Ref: req.Ref,
CategoryId: req.CategoryId,
})
if err != nil {
c.AbortWithStatusJSON(-1, gin.H{"msg": err.Error()})
return
}
res := &dto.InfoFileUploadRes{
Name: "yyy",
Url: "aaa",
}
c.JSON(200, res)
}
c.Abort方法原型
Abort可防止调用挂起的处理程序。请注意,这不会停止当前处理程序。
假设您有一个授权中间件来验证当前请求是否已被授权。
如果授权失败(例如:密码不匹配),请调用Abort以确保不会调用此请求的其余处理程序。
// Abort prevents pending handlers from being called. Note that this will not stop the current handler.
// Let's say you have an authorization middleware that validates that the current request is authorized.
// If the authorization fails (ex: the password does not match), call Abort to ensure the remaining handlers
// for this request are not called.
func (c *Context) Abort() {
c.index = abortIndex
}
abort序列方法
总结: gin框架中的终止当前请求的方式还是很有特点的,他必须是 Abort +return组合 或者直接抛panic异常。 gin中的Abort是很具有迷惑性的,大家要搞明白,gin中的Abort他是用于确保不会调用当前请求的其余处理程序,而不是立即中断当前请求!