You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

http.NewRequestWithContext创建的请求传递至下游服务中间件时丢失上下文值

根因

Go 中的 context.Context 是进程内的上下文对象,仅在当前服务的请求生命周期内生效,不会被自动序列化进HTTP请求报文。你在3000端口服务注入到上下文的自定义值,只会作用于当前服务的HTTP客户端请求流程,不会随着网络请求发送到8000端口的下游服务,所以下游自然读不到对应值。

解决方案

对于你场景里的简单字符串值,最简便的方式是通过自定义HTTP头传递:

  1. 调整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
}
  1. 调整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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 00:24:06