gogo-gin

Conditionally load or add another middleware in the chain during current middleware


When using Gin framework for Go, I'm writing some custom middleware. One of my new middleware will evaluate if the request coming in is from my front-end SPA. If it is, I want to also use the sessions middleware to create/load the user session info. If it is not, then I don't want to call that middleware.

I can't seem to find how (if possible) to do this. I was hoping I could either use an IF block when I'm defining my router.Use(xyz) statements, or better yet, tell my current middleware to load another one before I call the c.Next().

Example:

func MyMiddleware(c *gin.Context) {
    isFromFrontend := myFunctionToDetermine()
    c.Set("isFromFrontend", isFromFrontend)
    if isFromFrontend {
        <here is where i'd like to effectively call r.Use() again and pass the session middleware>
    }
    c.Next()
}

r := gin.Default()
r.Use(MyMiddleware)

I tried the other method of defining middleware where I:

  1. created a new function for MyMiddleware that accepts an instance of the router, so that I can try to call the .Use() method again from within my middleware; it doesn't error but it also doesn't seem to call it. I'm guessing that the middleware chain is already established before it is evaluated?

Is there a way to add a new middleware to the existing chain before it finishes processing?

Or is there maybe some other entirely different way to accomplish what I'm doing?


Solution

  • At the end of the day, gin middleware is defined as a gin.HandlerFunc, namely func(gin.Context).

    So conditionally calling a middleware is easy enough

    func setupMyMiddleware(conditional gin.HandlerFunc){
      return func(c gin.Context) {
         if c.GetBool("isFromFrontend") {
            conditional(c)
         }
         // Do something else, if necessary
         
         // Call the next handler
         c.Next()
      }
    }
    //...
    r := gin.Default()
    r.Use(setupMyMiddleware(myOtherMiddleware))
    

    It is basically like writing a conditional http Middleware, only the signature of the middleware is slightly different.