mirror of
https://github.com/gin-gonic/gin.git
synced 2025-10-22 01:12:16 +08:00
Merge branch 'master' into file-attachments
This commit is contained in:
commit
0eb1ee571f
13
context.go
13
context.go
@ -960,7 +960,18 @@ func (c *Context) NegotiateFormat(offered ...string) string {
|
||||
}
|
||||
for _, accepted := range c.Accepted {
|
||||
for _, offert := range offered {
|
||||
if accepted == offert {
|
||||
// According to RFC 2616 and RFC 2396, non-ASCII characters are not allowed in headers,
|
||||
// therefore we can just iterate over the string without casting it into []rune
|
||||
i := 0
|
||||
for ; i < len(accepted); i++ {
|
||||
if accepted[i] == '*' || offert[i] == '*' {
|
||||
return offert
|
||||
}
|
||||
if accepted[i] != offert[i] {
|
||||
break
|
||||
}
|
||||
}
|
||||
if i == len(accepted) {
|
||||
return offert
|
||||
}
|
||||
}
|
||||
|
@ -1171,17 +1171,41 @@ func TestContextNegotiationFormat(t *testing.T) {
|
||||
func TestContextNegotiationFormatWithAccept(t *testing.T) {
|
||||
c, _ := CreateTestContext(httptest.NewRecorder())
|
||||
c.Request, _ = http.NewRequest("POST", "/", nil)
|
||||
c.Request.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
|
||||
c.Request.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9;q=0.8")
|
||||
|
||||
assert.Equal(t, MIMEXML, c.NegotiateFormat(MIMEJSON, MIMEXML))
|
||||
assert.Equal(t, MIMEHTML, c.NegotiateFormat(MIMEXML, MIMEHTML))
|
||||
assert.Empty(t, c.NegotiateFormat(MIMEJSON))
|
||||
}
|
||||
|
||||
func TestContextNegotiationFormatWithWildcardAccept(t *testing.T) {
|
||||
c, _ := CreateTestContext(httptest.NewRecorder())
|
||||
c.Request, _ = http.NewRequest("POST", "/", nil)
|
||||
c.Request.Header.Add("Accept", "*/*")
|
||||
|
||||
assert.Equal(t, c.NegotiateFormat("*/*"), "*/*")
|
||||
assert.Equal(t, c.NegotiateFormat("text/*"), "text/*")
|
||||
assert.Equal(t, c.NegotiateFormat("application/*"), "application/*")
|
||||
assert.Equal(t, c.NegotiateFormat(MIMEJSON), MIMEJSON)
|
||||
assert.Equal(t, c.NegotiateFormat(MIMEXML), MIMEXML)
|
||||
assert.Equal(t, c.NegotiateFormat(MIMEHTML), MIMEHTML)
|
||||
|
||||
c, _ = CreateTestContext(httptest.NewRecorder())
|
||||
c.Request, _ = http.NewRequest("POST", "/", nil)
|
||||
c.Request.Header.Add("Accept", "text/*")
|
||||
|
||||
assert.Equal(t, c.NegotiateFormat("*/*"), "*/*")
|
||||
assert.Equal(t, c.NegotiateFormat("text/*"), "text/*")
|
||||
assert.Equal(t, c.NegotiateFormat("application/*"), "")
|
||||
assert.Equal(t, c.NegotiateFormat(MIMEJSON), "")
|
||||
assert.Equal(t, c.NegotiateFormat(MIMEXML), "")
|
||||
assert.Equal(t, c.NegotiateFormat(MIMEHTML), MIMEHTML)
|
||||
}
|
||||
|
||||
func TestContextNegotiationFormatCustom(t *testing.T) {
|
||||
c, _ := CreateTestContext(httptest.NewRecorder())
|
||||
c.Request, _ = http.NewRequest("POST", "/", nil)
|
||||
c.Request.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
|
||||
c.Request.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9;q=0.8")
|
||||
|
||||
c.Accepted = nil
|
||||
c.SetAccepted(MIMEJSON, MIMEXML)
|
||||
|
@ -1,137 +0,0 @@
|
||||
# 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.
|
||||
|
||||
```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
|
||||
```
|
Loading…
x
Reference in New Issue
Block a user