无法停止Go/Gin中的中间件链。

huangapple go评论77阅读模式
英文:

Can't stop a middleware chain in Go/Gin

问题

我想在继续处理请求之前检查会话,并且我有一个中间件来检查会话。这是端点:

profile.Use(session.CheckSession())
profile.GET("/:pid", func(c *gin.Context) {
    fmt.Println("Hit :pid")
    c.File("../../html/profile.html")
})

这是CheckSession()中间件,目前值是占位符:

func CheckSession() gin.HandlerFunc {
    return func(c *gin.Context) {
        session := sessions.Default(c)
        userID := session.Get("user_id")
        firstName := session.Get("firstname")
        lastName := session.Get("lastname")

        if userID == nil || firstName == nil || lastName == nil {
            fmt.Println("No session")
            c.Redirect(http.StatusSeeOther, "/sign-in")
            return
        }

        fmt.Println("Hit c.Next()")
        c.Next()
    }
}

日志:
无法停止Go/Gin中的中间件链。

首先,我访问了"/"路由,它重定向到/profile/:pid端点,如果会话无效,则重定向到/sign-in端点。我被重新路由到/sign-in端点,但/profile/:pid端点仍然执行完毕,即使从未调用c.Next()

尝试将它们放在if-else块中,以确保只执行c.Redirect()c.Next()中的一个,但函数仍然通过,并且链没有停止。

英文:

I want to check session before continuing with a request and I have a middleware to check that session. This is the endpoint:

profile.Use(session.CheckSession())
profile.GET("/:pid", func(c *gin.Context) {
	fmt.Println("Hit :pid")
	c.File("../../html/profile.html")
})

And this is the CheckSession() middleware, values are placeholders atm:

func CheckSession() gin.HandlerFunc {
	return func(c *gin.Context) {
		session := sessions.Default(c)
		userID := session.Get("user_id")
		firstName := session.Get("firstname")
		lastName := session.Get("lastname")

		if userID == nil || firstName == nil || lastName == nil {
			fmt.Println("No session")
			c.Redirect(http.StatusSeeOther, "/sign-in")
			return
		}

		fmt.Println("Hit c.Next()")
		c.Next()
	}
}

The logs:
无法停止Go/Gin中的中间件链。

At first, I hit "/" route, which redirects to /profile/:pid endpoint, which redirects to /sign-in endpoint in case of 'invalid' session. I get re-routed to the /sign-in endpoint, but the /profile/:pid endpoint still finishes execution, even without hitting c.Next() ever

Tried putting them in if-else blocks to make sure only one of c.Redirect() and c.Next() was being executed and so was happening, yet function was still passed and the chain didn't stop.

答案1

得分: 0

错误是由于没有手动中止中间件链引起的。
c.Redirect() 不会停止中间件链,你应该手动调用 c.Abort() 来阻止执行剩余的处理程序。

c.Abort() 工具提示:
>Abort 防止待处理程序被调用。请注意,这不会停止当前处理程序的执行。假设你有一个授权中间件,用于验证当前请求是否经过授权。如果授权失败(例如密码不匹配),调用 Abort 来确保不会调用此请求的剩余处理程序。

英文:

The error was caused by not aborting middleware chain manually.
c.Redirect() doesn't stop the middleware chain, you should manually call c.Abort() to prevent execution of the remaining handlers.

c.Abort() Tooltip:
>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.

huangapple
  • 本文由 发表于 2023年1月12日 15:19:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/75092774.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定