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 ?