gin框架 gin.Context中的Abort方法使用注意事项 - gin框架中立刻中断当前请求的方法

时间:2024-07-09 14:11:51

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他是用于确保不会调用当前请求的其余处理程序,而不是立即中断当前请求!