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

Golang中API Handler无法访问中间件Context值的问题

问题:中间件存入Context的用户ID无法在Handler中获取

需求是在Auth中间件验证JWT后,将用户ID存入请求Context并传递给后续API Handler使用。目前中间件内部能正常获取Context中的值,但Handler中始终无法访问该值。

关键代码

路由代码

addProductDistHandler := middlewares.Auth(client, log)
r.Handle("/add-product-distributor", addProductDistHandler(http.HandlerFunc(handlers.AddProductDist(log, client))))

Auth中间件代码

logger.InfoLog.Printf("user.ObjectID %T",user.ObjectID)
logger.InfoLog.Printf("user.ObjectID %v",user.ObjectID)

// Add user ID to request context
ctx := context.WithValue(r.Context(), userIDKey, user.ObjectID)
r = r.WithContext(ctx)
logger.InfoLog.Printf("context : %T => %v",ctx,ctx)
distID, _ := r.Context().Value(userIDKey).(string)
logger.InfoLog.Printf("distID : %s",distID)
// Call the next handler
next.ServeHTTP(w, r)

Handler代码

distID, ok := r.Context().Value(userIDKey).(string)
if !ok {
    logger.InfoLog.Println("userIDKey is not of type string or is nil")
    helpers.EncodeJSON(w, http.StatusInternalServerError, "userIDKey is not of type string or is nil", nil)
    return
}

日志信息

INFO                    2024/06/21 23:36:46 cookie retrieved successfully
INFO                    2024/06/21 23:36:46 ObjectID("66757f98606b94271a05cd24")
INFO                    2024/06/21 23:36:46 user.ObjectID string
INFO                    2024/06/21 23:36:46 user.ObjectID 66757f98606b94271a05cd24
INFO                    2024/06/21 23:36:46 context : *context.valueCtx => context.Background.WithValue(type *http.contextKey, val <not Stringer>).WithValue(type *http.contextKey, val [::1]:8000).WithCancel.WithCancel.WithValue(type mux.contextKey, val <not Stringer>).WithValue(type mux.contextKey, val <not Stringer>).WithValue(type middlewares.contextKey, val 66757f98606b94271a05cd24)
INFO                    2024/06/21 23:36:46 distID : 66757f98606b94271a05cd24
INFO                    2024/06/21 23:36:46 userIDKey is not of type string or is nil

解决方案

问题核心是**userIDKey的定义不统一**:Go中context.WithValue的键是基于「类型+值」来区分的,如果中间件和Handler各自在不同包中定义了同名的contextKey类型,这两个类型属于不同的标识,导致Handler无法通过自己的userIDKey取出中间件存入的值。

修复步骤:

  1. 在中间件包中导出统一的UserIDKey常量:
package middlewares

type contextKey string

// 导出该键,供其他包直接引用
const UserIDKey contextKey = "userID"
  1. 在Handler中直接使用中间件包导出的UserIDKey取值:
import "your-project-path/middlewares"

// ...

distID, ok := r.Context().Value(middlewares.UserIDKey).(string)
if !ok {
    // 错误处理逻辑
}
  1. 额外校验:确保存入Context的值类型与取出时断言的类型一致。从日志看,中间件中user.ObjectID是string类型,Handler中断言为string是正确的;如果实际是primitive.ObjectID,则要对应调整断言类型。

内容的提问来源于stack exchange,提问作者user25606885

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 04:52:40