forked from gin-gonic/gin
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
document: add docs dir and middleware document (gin-gonic#1521)
* init docs dir * add middleware document * fix indent * update docs
- Loading branch information
Showing
1 changed file
with
137 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
``` |