Skip to content
This repository has been archived by the owner on Oct 27, 2023. It is now read-only.

gin.context拿不到kratos中间件修改的context #6

Open
straysh opened this issue Sep 23, 2022 · 0 comments
Open

gin.context拿不到kratos中间件修改的context #6

straysh opened this issue Sep 23, 2022 · 0 comments

Comments

@straysh
Copy link

straysh commented Sep 23, 2022

现象:增加了kratos的tracing中间件后,在gin.Context中获取不到traceid。

示例代码:

func NewHTTPServer(c *conf.Server, logger log.Logger) *http.Server {
	engine := gin.New()
	engine.Use(gin.Logger(), kgin.Middlewares(
		recovery.Recovery(),
		tracing.Server(),
	))
	engine.GET("/dummy", func(c *gin.Context) {
		ctx := c.Request.Context()
		span := trace.SpanContextFromContext(ctx)
		if span.HasTraceID() {
			fmt.Println("found traceid ", span.TraceID().String())
		} else {
			fmt.Println("no traceid")
		}
	})
	srv := http.NewServer(http.Address(":18200"))
	srv.HandlePrefix("/", engine)
	return srv
}

请求示例:

curl http://127.0.0.1:18200/dummy
"no traceid"

原因:
kratos中间件在调用next函数时,接收context为参数并传递给下一个next处理。tracing.Server()中间件使用WithValue方法延长了context链。

// Handler defines the handler invoked by Middleware.
type Handler func(ctx context.Context, req interface{}) (interface{}, error)

在原生kratos中,context是传递的,这没有问题。但gin里总是使用gin.Conetxt。在gin.Context链之上的上下文都无法检索到。

因此需要在kratos中间件处理完成时,将最后的context重新绑定到gin.Request上。

next := func(ctx context.Context, req interface{}) (interface{}, error) {
	c.Next()
	var err error
	if c.Writer.Status() >= 400 {
		err = errors.Errorf(c.Writer.Status(), errors.UnknownReason, errors.UnknownReason)
	}
	return c.Writer, err
}
next = chain(next)
ctx := NewGinContext(c.Request.Context(), c)
c.Request = c.Request.WithContext(ctx)
if ginCtx, ok := FromGinContext(ctx); ok {
	thttp.SetOperation(ctx, ginCtx.FullPath())
}
next(c.Request.Context(), c.Request) // 注意:这里的next实际是kratos注册的第一个中间件,所有其他中间件依次执行后将调用上面的next回调函数。需要在这里将最后的context重新绑定到gin.Request。
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant