http.NewRequestWithContext创建的请求传递至下游服务中间件时丢失上下文值
根因
Go 中的 context.Context 是进程内的上下文对象,仅在当前服务的请求生命周期内生效,不会被自动序列化进HTTP请求报文。你在3000端口服务注入到上下文的自定义值,只会作用于当前服务的HTTP客户端请求流程,不会随着网络请求发送到8000端口的下游服务,所以下游自然读不到对应值。
解决方案
对于你场景里的简单字符串值,最简便的方式是通过自定义HTTP头传递:
- 调整3000端口的请求发送逻辑,把自定义值放到请求头中:
func GetDataAndSolve() http.Handler { r := chi.NewRouter() r.Use(middleware.Logger) r.Get("/tasks/str", func(rw http.ResponseWriter, r *http.Request) { // 原有逻辑不变 taskCtx := context.WithValue(r.Context(), "str", "strVar") postReq, err := http.NewRequestWithContext( taskCtx, "POST", "http://localhost:8000/tasks/solution", bytes.NewBuffer([]byte("something")), ) postReq.Header.Set("Content-Type", "application/json") // 新增:把自定义值放到自定义请求头 postReq.Header.Set("X-Custom-Str", "strVar") if err != nil { return } resp, err := http.DefaultClient.Do(postReq) // 后续原有逻辑不变 }) return r }
- 调整8000端口的Solver中间件,从请求头读取值,可按需注入到当前服务的上下文供后续逻辑使用:
func Solver(next http.Handler) http.Handler { return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { // 从请求头读取自定义值 strVal := r.Header.Get("X-Custom-Str") if strVal == "" { rw.WriteHeader(http.StatusBadRequest) return } // 可选:将值注入当前服务的上下文,供后续 handler 读取 ctx := context.WithValue(r.Context(), "str", strVal) ctxWithResult := context.WithValue(ctx, "result", mockFunc(ctx)) next.ServeHTTP(rw, r.Clone(ctxWithResult)) }) }
补充说明
如果需要传递复杂的结构化数据,可以将数据序列化后放到请求体中,下游服务解析请求体读取即可;如果需要传递超时、取消这类控制信号,可以通过标准的超时头传递超时时间,下游服务自行绑定对应超时的上下文即可。
内容的提问来源于stack exchange,提问作者mcv_dev
相关产品推荐
相关产品推荐

