mirror of
https://github.com/gin-gonic/gin.git
synced 2025-10-19 15:57:48 +08:00
Merge e00b80a59113c05796b61b73a4a5fd923b3a52d4 into db9174ae0c2587fe1c755def0f88cb9aba9e9641
This commit is contained in:
commit
352bd0ea49
76
context.go
76
context.go
@ -5,6 +5,7 @@
|
|||||||
package gin
|
package gin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@ -15,6 +16,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -41,9 +43,10 @@ const abortIndex int8 = math.MaxInt8 / 2
|
|||||||
// Context is the most important part of gin. It allows us to pass variables between middleware,
|
// Context is the most important part of gin. It allows us to pass variables between middleware,
|
||||||
// manage the flow, validate the JSON of a request and render a JSON response for example.
|
// manage the flow, validate the JSON of a request and render a JSON response for example.
|
||||||
type Context struct {
|
type Context struct {
|
||||||
writermem responseWriter
|
context.Context //point to parent
|
||||||
Request *http.Request
|
writermem responseWriter
|
||||||
Writer ResponseWriter
|
Request *http.Request
|
||||||
|
Writer ResponseWriter
|
||||||
|
|
||||||
Params Params
|
Params Params
|
||||||
handlers HandlersChain
|
handlers HandlersChain
|
||||||
@ -86,6 +89,37 @@ func (c *Context) reset() {
|
|||||||
c.formCache = nil
|
c.formCache = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type gin_context string
|
||||||
|
|
||||||
|
const gin_context_key gin_context = "gin_real_context"
|
||||||
|
|
||||||
|
// GinContext try to Get gin.Context from context.Context
|
||||||
|
func GinContext(ctx context.Context) (*Context, error) {
|
||||||
|
v := ctx.Value(gin_context_key)
|
||||||
|
if gc, ok := v.(*Context); ok {
|
||||||
|
return gc, nil
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf("GinContext fail,TypeOf(v):%s", reflect.TypeOf(v))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustGinContext try to gin.Context from context.Context
|
||||||
|
// Will panic if fail
|
||||||
|
func MustGinContext(ctx context.Context) *Context {
|
||||||
|
if gc, err := GinContext(ctx); err == nil {
|
||||||
|
return gc
|
||||||
|
} else {
|
||||||
|
panic(fmt.Sprintf("MustGinContext fail:%s", err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewContext wrap gin.Context with context.Context
|
||||||
|
func NewContext(e *Engine) *Context {
|
||||||
|
c := &Context{engine: e}
|
||||||
|
c.Context = context.WithValue(context.Background(), gin_context_key, c) //With a value point to gin.Context
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
// Copy returns a copy of the current context that can be safely used outside the request's scope.
|
// Copy returns a copy of the current context that can be safely used outside the request's scope.
|
||||||
// This has to be used when the context has to be passed to a goroutine.
|
// This has to be used when the context has to be passed to a goroutine.
|
||||||
func (c *Context) Copy() *Context {
|
func (c *Context) Copy() *Context {
|
||||||
@ -1028,34 +1062,6 @@ func (c *Context) SetAccepted(formats ...string) {
|
|||||||
c.Accepted = formats
|
c.Accepted = formats
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************/
|
|
||||||
/***** GOLANG.ORG/X/NET/CONTEXT *****/
|
|
||||||
/************************************/
|
|
||||||
|
|
||||||
// Deadline returns the time when work done on behalf of this context
|
|
||||||
// should be canceled. Deadline returns ok==false when no deadline is
|
|
||||||
// set. Successive calls to Deadline return the same results.
|
|
||||||
func (c *Context) Deadline() (deadline time.Time, ok bool) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Done returns a channel that's closed when work done on behalf of this
|
|
||||||
// context should be canceled. Done may return nil if this context can
|
|
||||||
// never be canceled. Successive calls to Done return the same value.
|
|
||||||
func (c *Context) Done() <-chan struct{} {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Err returns a non-nil error value after Done is closed,
|
|
||||||
// successive calls to Err return the same error.
|
|
||||||
// If Done is not yet closed, Err returns nil.
|
|
||||||
// If Done is closed, Err returns a non-nil error explaining why:
|
|
||||||
// Canceled if the context was canceled
|
|
||||||
// or DeadlineExceeded if the context's deadline passed.
|
|
||||||
func (c *Context) Err() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Value returns the value associated with this context for key, or nil
|
// Value returns the value associated with this context for key, or nil
|
||||||
// if no value is associated with key. Successive calls to Value with
|
// if no value is associated with key. Successive calls to Value with
|
||||||
// the same key returns the same result.
|
// the same key returns the same result.
|
||||||
@ -1064,8 +1070,10 @@ func (c *Context) Value(key interface{}) interface{} {
|
|||||||
return c.Request
|
return c.Request
|
||||||
}
|
}
|
||||||
if keyAsString, ok := key.(string); ok {
|
if keyAsString, ok := key.(string); ok {
|
||||||
val, _ := c.Get(keyAsString)
|
val, ok := c.Get(keyAsString)
|
||||||
return val
|
if ok {
|
||||||
|
return val
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return c.Context.Value(key)
|
||||||
}
|
}
|
||||||
|
@ -1868,6 +1868,42 @@ func TestContextResetInHandler(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func UserFunc2Mock(ctx context.Context, t *testing.T) {
|
||||||
|
v, ok := ctx.Value("user_self_defined_value").(string)
|
||||||
|
assert.Equal(t, true, ok)
|
||||||
|
assert.Equal(t, "vvvvv", v)
|
||||||
|
assert.NotPanics(t, func() {
|
||||||
|
gc := MustGinContext(ctx) //get gin.Context back as need
|
||||||
|
assert.NotEqual(t, gc, nil)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func UserFunc3Mock(ctx context.Context, t *testing.T) {
|
||||||
|
assert.Panics(t, func() {
|
||||||
|
gc := MustGinContext(ctx) //get gin.Context back as need
|
||||||
|
assert.Equal(t, gc, nil)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func UserFunc1Mock(ctx context.Context, t *testing.T) {
|
||||||
|
//add user defined value
|
||||||
|
ctx = context.WithValue(ctx, "user_self_defined_value", "vvvvv")
|
||||||
|
|
||||||
|
//do user's business
|
||||||
|
UserFunc2Mock(ctx, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewContextMustGin(t *testing.T) {
|
||||||
|
ctx := NewContext(nil)
|
||||||
|
UserFunc1Mock(ctx, t) //use gin.Context as standard context
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStandardContext(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
UserFunc3Mock(ctx, t)
|
||||||
|
}
|
||||||
|
|
||||||
func TestRaceParamsContextCopy(t *testing.T) {
|
func TestRaceParamsContextCopy(t *testing.T) {
|
||||||
DefaultWriter = os.Stdout
|
DefaultWriter = os.Stdout
|
||||||
router := Default()
|
router := Default()
|
||||||
|
2
gin.go
2
gin.go
@ -156,7 +156,7 @@ func Default() *Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (engine *Engine) allocateContext() *Context {
|
func (engine *Engine) allocateContext() *Context {
|
||||||
return &Context{engine: engine}
|
return NewContext(engine)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delims sets template left and right delims and returns a Engine instance.
|
// Delims sets template left and right delims and returns a Engine instance.
|
||||||
|
4
go.mod
4
go.mod
@ -3,6 +3,7 @@ module github.com/gin-gonic/gin
|
|||||||
go 1.12
|
go 1.12
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3
|
||||||
github.com/gin-contrib/sse v0.1.0
|
github.com/gin-contrib/sse v0.1.0
|
||||||
github.com/go-playground/locales v0.12.1 // indirect
|
github.com/go-playground/locales v0.12.1 // indirect
|
||||||
github.com/go-playground/universal-translator v0.16.0 // indirect
|
github.com/go-playground/universal-translator v0.16.0 // indirect
|
||||||
@ -12,6 +13,9 @@ require (
|
|||||||
github.com/mattn/go-isatty v0.0.9
|
github.com/mattn/go-isatty v0.0.9
|
||||||
github.com/stretchr/testify v1.4.0
|
github.com/stretchr/testify v1.4.0
|
||||||
github.com/ugorji/go/codec v1.1.7
|
github.com/ugorji/go/codec v1.1.7
|
||||||
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58 // indirect
|
||||||
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d // indirect
|
||||||
gopkg.in/go-playground/assert.v1 v1.2.1 // indirect
|
gopkg.in/go-playground/assert.v1 v1.2.1 // indirect
|
||||||
gopkg.in/go-playground/validator.v9 v9.29.1
|
gopkg.in/go-playground/validator.v9 v9.29.1
|
||||||
gopkg.in/yaml.v2 v2.2.2
|
gopkg.in/yaml.v2 v2.2.2
|
||||||
|
2
go.sum
2
go.sum
@ -39,4 +39,4 @@ gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8
|
|||||||
gopkg.in/go-playground/validator.v9 v9.29.1 h1:SvGtYmN60a5CVKTOzMSyfzWDeZRxRuGvRQyEAKbw1xc=
|
gopkg.in/go-playground/validator.v9 v9.29.1 h1:SvGtYmN60a5CVKTOzMSyfzWDeZRxRuGvRQyEAKbw1xc=
|
||||||
gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
|
gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
|
||||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
Loading…
x
Reference in New Issue
Block a user