gin/docs/how-to-build-an-effective-m...

2.5 KiB

How to build one effective middleware?

Consitituent part

The middleware has two parts:

  • part one is what is executed once, when you initialize your middleware. That's where you set up all the global objects, logicals etc. Everything that happens one per application lifetime.

  • part two is what executes on every request. For example, a database middleware you simply inject your "global" database object into the context. Once it's inside the context, you can retrieve it from within other middlewares and your handler function.

func funcName(params string) gin.HandlerFunc {
    // <---
    // This is part one
    // --->
    // The follow code is an example
    if err := check(params); err != nil {
        panic(err)
    }

    return func(c *gin.Context) {
        // <---
        // This is part two
        // --->
        // The follow code is an example
        c.Set("TestVar", params)
        c.Next()    
    }
}

Execution process

Firstly, we have the follow example code:

func main() {
	router := gin.Default()

	router.Use(globalMiddleware())

	router.GET("/rest/n/api/*some", mid1(), mid2(), handler)

	router.Run()
}

func globalMiddleware() gin.HandlerFunc {
	fmt.Println("globalMiddleware...1")

	return func(c *gin.Context) {
		fmt.Println("globalMiddleware...2")
		c.Next()
		fmt.Println("globalMiddleware...3")
	}
}

func handler(c *gin.Context) {
	fmt.Println("exec handler.")
}

func mid1() gin.HandlerFunc {
	fmt.Println("mid1...1")

	return func(c *gin.Context) {

		fmt.Println("mid1...2")
		c.Next()
		fmt.Println("mid1...3")
	}
}

func mid2() gin.HandlerFunc {
	fmt.Println("mid2...1")

	return func(c *gin.Context) {
		fmt.Println("mid2...2")
		c.Next()
		fmt.Println("mid2...3")
	}
}

According to Consitituent part said, when we run the gin process, part one will execute firstly and will print the follow information:

globalMiddleware...1
mid1...1
mid2...1

And init order are:

globalMiddleware...1
    |
    v
mid1...1
    |
    v
mid2...1

When we curl one request curl -v localhost:8080/rest/n/api/some, part two will execute their middleware and output the following information:

globalMiddleware...2
mid1...2
mid2...2
exec handler.
mid2...3
mid1...3
globalMiddleware...3

In other words, run order are:

globalMiddleware...2
    |
    v
mid1...2
    |
    v
mid2...2
    |
    v
exec handler.
    |
    v
mid2...3
    |
    v
mid1...3
    |
    v
globalMiddleware...3