diff --git a/context.go b/context.go index 5dc7f8a0..065cd122 100644 --- a/context.go +++ b/context.go @@ -5,6 +5,7 @@ package gin import ( + "context" "errors" "fmt" "io" @@ -15,6 +16,7 @@ import ( "net/http" "net/url" "os" + "reflect" "strings" "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, // manage the flow, validate the JSON of a request and render a JSON response for example. type Context struct { - writermem responseWriter - Request *http.Request - Writer ResponseWriter + context.Context //point to parent + writermem responseWriter + Request *http.Request + Writer ResponseWriter Params Params handlers HandlersChain @@ -75,6 +78,25 @@ func (c *Context) reset() { c.Accepted = nil } +type gin_context string + +const gin_context_key gin_context = "gin_real_context" + +func MustGinContext(ctx context.Context) *Context { + v := ctx.Value(gin_context_key) + if gc, ok := v.(*Context); ok { + return gc + } else { + panic(fmt.Sprintf("MustGinContext fail,TypeOf(v):%s", reflect.TypeOf(v))) + } +} + +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. // This has to be used when the context has to be passed to a goroutine. func (c *Context) Copy() *Context { @@ -985,34 +1007,6 @@ func (c *Context) SetAccepted(formats ...string) { 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 // if no value is associated with key. Successive calls to Value with // the same key returns the same result. @@ -1021,8 +1015,10 @@ func (c *Context) Value(key interface{}) interface{} { return c.Request } if keyAsString, ok := key.(string); ok { - val, _ := c.Get(keyAsString) - return val + val, ok := c.Get(keyAsString) + if ok { + return val + } } - return nil + return c.Context.Value(key) } diff --git a/context_test.go b/context_test.go index 0da5fbe6..909fd1e0 100644 --- a/context_test.go +++ b/context_test.go @@ -1812,3 +1812,26 @@ func TestContextResetInHandler(t *testing.T) { c.Next() }) } + +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 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 +} diff --git a/gin.go b/gin.go index 2d24092f..aa23a33b 100644 --- a/gin.go +++ b/gin.go @@ -156,7 +156,7 @@ func Default() *Engine { } func (engine *Engine) allocateContext() *Context { - return &Context{engine: engine} + return NewContext(engine) } // Delims sets template left and right delims and returns a Engine instance. diff --git a/go.mod b/go.mod index 01227574..f695e9a7 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/gin-gonic/gin go 1.12 require ( + github.com/davecgh/go-spew v1.1.1 // indirect github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3 github.com/golang/protobuf v1.3.0 github.com/json-iterator/go v1.1.5 @@ -11,7 +12,9 @@ require ( github.com/modern-go/reflect2 v1.0.1 // indirect github.com/stretchr/testify v1.3.0 github.com/ugorji/go/codec v0.0.0-20190204201341-e444a5086c43 - golang.org/x/net v0.0.0-20190301231341-16b79f2e4e95 + 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/validator.v8 v8.18.2 gopkg.in/yaml.v2 v2.2.2 diff --git a/go.sum b/go.sum index 84cf8378..60638439 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3 h1:t8FVkw33L+wilf2QiWkw0UV77qRpcH/JHPKGpKa2E8g= github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= github.com/golang/protobuf v1.3.0 h1:kbxbvI4Un1LUWKxufD+BiE6AEExYYgkQLQmLFqA1LFk= @@ -14,6 +16,7 @@ github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9 github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -21,13 +24,21 @@ github.com/ugorji/go v1.1.2 h1:JON3E2/GPW2iDNGoSAusl1KDf5TRQ8k8q7Tp097pZGs= github.com/ugorji/go v1.1.2/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ= github.com/ugorji/go/codec v0.0.0-20190204201341-e444a5086c43 h1:BasDe+IErOQKrMVXab7UayvSlIpiyGwRvuX3EKYY7UA= github.com/ugorji/go/codec v0.0.0-20190204201341-e444a5086c43/go.mod h1:iT03XoTwV7xq/+UGwKO3UbC1nNNlopQiY61beSdrtOA= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190301231341-16b79f2e4e95 h1:fY7Dsw114eJN4boqzVSbpVHO6rTdhq6/GnXeu+PKnzU= -golang.org/x/net v0.0.0-20190301231341-16b79f2e4e95/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +google.golang.org/genproto v0.0.0-20180831171423-11092d34479b h1:lohp5blsw53GBXtLyLNaTXPXS9pJ1tiTw61ZHUoE9Qw= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=