diff --git a/net/ghttp/ghttp.go b/net/ghttp/ghttp.go index 2bd9a2aa2..0b98e64b1 100644 --- a/net/ghttp/ghttp.go +++ b/net/ghttp/ghttp.go @@ -21,6 +21,7 @@ import ( "github.com/gogf/gf/v2/net/goai" "github.com/gogf/gf/v2/net/gsvc" "github.com/gogf/gf/v2/os/gcache" + "github.com/gogf/gf/v2/os/gctx" "github.com/gogf/gf/v2/os/gsession" "github.com/gogf/gf/v2/util/gtag" ) @@ -129,19 +130,19 @@ const ( ) const ( - supportedHttpMethods = "GET,PUT,POST,DELETE,PATCH,HEAD,CONNECT,OPTIONS,TRACE" - defaultMethod = "ALL" - routeCacheDuration = time.Hour - ctxKeyForRequest = "gHttpRequestObject" - contentTypeXml = "text/xml" - contentTypeHtml = "text/html" - contentTypeJson = "application/json" - swaggerUIPackedPath = "/goframe/swaggerui" - responseHeaderTraceID = "Trace-ID" - responseHeaderContentLength = "Content-Length" - specialMethodNameInit = "Init" - specialMethodNameShut = "Shut" - specialMethodNameIndex = "Index" + supportedHttpMethods = "GET,PUT,POST,DELETE,PATCH,HEAD,CONNECT,OPTIONS,TRACE" + defaultMethod = "ALL" + routeCacheDuration = time.Hour + ctxKeyForRequest gctx.StrKey = "gHttpRequestObject" + contentTypeXml = "text/xml" + contentTypeHtml = "text/html" + contentTypeJson = "application/json" + swaggerUIPackedPath = "/goframe/swaggerui" + responseHeaderTraceID = "Trace-ID" + responseHeaderContentLength = "Content-Length" + specialMethodNameInit = "Init" + specialMethodNameShut = "Shut" + specialMethodNameIndex = "Index" ) const ( diff --git a/net/ghttp/ghttp_request.go b/net/ghttp/ghttp_request.go index f27d34b58..e41b5cc84 100644 --- a/net/ghttp/ghttp_request.go +++ b/net/ghttp/ghttp_request.go @@ -7,7 +7,6 @@ package ghttp import ( - "context" "fmt" "net/http" "strings" @@ -40,7 +39,6 @@ type Request struct { // Private attributes for internal usage purpose. // ================================================================================================================= - context context.Context // Custom context for internal usage purpose. handlers []*HandlerItemParsed // All matched handlers containing handler, hook and middleware for this request. serveHandler *HandlerItemParsed // Real handler serving for this request, not hook or middleware. handlerResponse interface{} // Handler response object for Request/Response handler. diff --git a/net/ghttp/ghttp_request_middleware.go b/net/ghttp/ghttp_request_middleware.go index e73f3ded2..f1ef4b79f 100644 --- a/net/ghttp/ghttp_request_middleware.go +++ b/net/ghttp/ghttp_request_middleware.go @@ -45,7 +45,8 @@ func (m *middleware) Next() { // Router values switching. m.request.routerMap = item.Values - ctx := m.request.context + + var ctx = m.request.Context() gutil.TryCatch(ctx, func(ctx context.Context) { // Execute bound middleware array of the item if it's not empty. if m.handlerMDIndex < len(item.Handler.Middleware) { diff --git a/net/ghttp/ghttp_request_param_ctx.go b/net/ghttp/ghttp_request_param_ctx.go index 5c55148dd..9e7cc1a5e 100644 --- a/net/ghttp/ghttp_request_param_ctx.go +++ b/net/ghttp/ghttp_request_param_ctx.go @@ -46,29 +46,38 @@ func RequestFromCtx(ctx context.Context) *Request { // This function overwrites the http.Request.Context function. // See GetCtx. func (r *Request) Context() context.Context { - if r.context == nil { - // It forbids the context manually done, - // to make the context can be propagated to asynchronous goroutines. - r.context = &neverDoneCtx{ - r.Request.Context(), - } - r.context = gctx.WithCtx(r.context) + var ctx = r.Request.Context() + // Check and inject Request object into context. + if RequestFromCtx(ctx) == nil { + // Inject Request object into context. + ctx = context.WithValue(ctx, ctxKeyForRequest, r) + // Add default tracing info if using default tracing provider. + ctx = gctx.WithCtx(ctx) + // Update the values of the original HTTP request. + *r.Request = *r.Request.WithContext(ctx) } - // Inject Request object into context. - if RequestFromCtx(r.context) == nil { - r.context = context.WithValue(r.context, ctxKeyForRequest, r) - } - return r.context + return ctx } // GetCtx retrieves and returns the request's context. +// Its alias of function Context,to be relevant with function SetCtx. func (r *Request) GetCtx() context.Context { return r.Context() } +// GetNeverDoneCtx creates and returns a never done context object, +// which forbids the context manually done, to make the context can be propagated to asynchronous goroutines, +// which will not be affected by the HTTP request ends. +// +// This change is considered for common usage habits of developers for context propagation +// in multiple goroutines creation in one HTTP request. +func (r *Request) GetNeverDoneCtx() context.Context { + return &neverDoneCtx{r.Context()} +} + // SetCtx custom context for current request. func (r *Request) SetCtx(ctx context.Context) { - r.context = ctx + *r.Request = *r.WithContext(ctx) } // GetCtxVar retrieves and returns a Var with a given key name. @@ -84,5 +93,7 @@ func (r *Request) GetCtxVar(key interface{}, def ...interface{}) *gvar.Var { // SetCtxVar sets custom parameter to context with key-value pairs. func (r *Request) SetCtxVar(key interface{}, value interface{}) { - r.context = context.WithValue(r.Context(), key, value) + var ctx = r.Context() + ctx = context.WithValue(ctx, key, value) + *r.Request = *r.Request.WithContext(ctx) }