Description
When we need to downgrade the service, we need to directly reject some urls, but still provide some urls.
In this scenario, the middleware needs to be able to obtain some parameters (such as url level) declared by the url during registration.
Current situation
Since gin.Context.Handler() return the last handler, so i do this:
package main
import (
"strings"
"github.com/gin-gonic/gin"
)
var currentAllowLevel = 50
const (
urlLevelKey = "__urlLevelKey__"
)
func MarkUrlLevelMiddleware(urlLevel int) func(c *gin.Context) {
return func(c *gin.Context) {
c.Set(urlLevelKey, urlLevel)
}
}
func downgradeMiddleware(c *gin.Context) {
if lastHandlerName := c.HandlerName() ; ! strings.HasSuffix( lastHandlerName , "MarkUrlLevelMiddleware") {
return
}
// exec the last Handler
c.Handler()(c)
// get the url level parameter
leveInterface, ok := c.Get(urlLevelKey)
if !ok {
return
}
urlLevel := leveInterface.(int)
if urlLevel < currentAllowLevel {
// reject service drectly
c.AbortWithStatus( 503 )
}
}
func main() {
g := gin.Default()
g.Use(downgradeMiddleware)
g.GET("/high/level/url", func(c *gin.Context) {
c.String(200, "/lower/level/url")
}, MarkUrlLevelMiddleware(80) )
// will be blocked urls:
g.GET("/lower/level/url", func(c *gin.Context) {
c.String(200, "/lower/level/url")
}, MarkUrlLevelMiddleware(20) )
g.GET("/without/level/url", func(c *gin.Context) {
c.String(200, "/lower/level/url")
} )
g.Run(":9000")
}
It's not elegant !!
Expectations
It it possible take parameters when registering url?
Expand a parameter for gin.Context, and bring it to gin.Context when matching the route
type Context struct {
// ...
Params Params
handlers HandlersChain
index int8
fullPath string
HookParam interface // expand an param
//...
package main
import (
"github.com/gin-gonic/gin"
)
var currentAllowLevel = 50
func downgradeMiddlewareV2(c *gin.Context) {
if c.HookParam != nil {
urlLevel := c.HookParam.(int)
if urlLevel < currentAllowLevel {
// reject service drectly
c.AbortWithStatus( 503 )
}
}
}
func main() {
g := gin.Default()
g.Use(downgradeMiddlewareV2)
g.GETWithParam("/high/level/url", 80, func(c *gin.Context) {
c.String(200, "/lower/level/url")
} )
// will be blocked urls:
g.GETWithParam("/lower/level/url", 20, func(c *gin.Context) {
c.String(200, "/lower/level/url")
} )
// normal
g.GET("/without/level/url", func(c *gin.Context) {
c.String(200, "/lower/level/url")
} )
g.Run(":9000")
}
Are there any other suggestions ?