|
@@ -0,0 +1,137 @@
|
|
|
|
|
+# How to build one effective middleware?
|
|
|
|
|
+
|
|
|
|
|
+## Consitituent part
|
|
|
|
|
+
|
|
|
|
|
+The middleware has two parts:
|
|
|
|
|
+
|
|
|
|
|
+ - part one is what is executed once, when you initalize 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 furnction.
|
|
|
|
|
+
|
|
|
|
|
+```go
|
|
|
|
|
+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:
|
|
|
|
|
+
|
|
|
|
|
+```go
|
|
|
|
|
+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](#consitituent-part) said, when we run the gin process, **part one** will execute firstly and will print the follow information:
|
|
|
|
|
+
|
|
|
|
|
+```go
|
|
|
|
|
+globalMiddleware...1
|
|
|
|
|
+mid1...1
|
|
|
|
|
+mid2...1
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+And init order are:
|
|
|
|
|
+
|
|
|
|
|
+```go
|
|
|
|
|
+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:
|
|
|
|
|
+
|
|
|
|
|
+```go
|
|
|
|
|
+globalMiddleware...2
|
|
|
|
|
+mid1...2
|
|
|
|
|
+mid2...2
|
|
|
|
|
+exec handler.
|
|
|
|
|
+mid2...3
|
|
|
|
|
+mid1...3
|
|
|
|
|
+globalMiddleware...3
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+In other words, run order are:
|
|
|
|
|
+
|
|
|
|
|
+```go
|
|
|
|
|
+globalMiddleware...2
|
|
|
|
|
+ |
|
|
|
|
|
+ v
|
|
|
|
|
+mid1...2
|
|
|
|
|
+ |
|
|
|
|
|
+ v
|
|
|
|
|
+mid2...2
|
|
|
|
|
+ |
|
|
|
|
|
+ v
|
|
|
|
|
+exec handler.
|
|
|
|
|
+ |
|
|
|
|
|
+ v
|
|
|
|
|
+mid2...3
|
|
|
|
|
+ |
|
|
|
|
|
+ v
|
|
|
|
|
+mid1...3
|
|
|
|
|
+ |
|
|
|
|
|
+ v
|
|
|
|
|
+globalMiddleware...3
|
|
|
|
|
+```
|