如何用Go的net/http根据会话Cookie将请求分配到主从数据库
嗨,针对你的需求,我有几个简洁又优雅的实现方式,完全不需要前端传参数,也能完美适配HttpOnly Cookie的场景:
1. 最直接:统一处理函数分发
你可以给/home注册一个统一的处理函数,在里面判断Cookie是否存在,再分发到对应的主库/从库处理逻辑:
// 注册路由 http.HandleFunc("/home", func(w http.ResponseWriter, r *http.Request) { // 检查session Cookie是否存在 _, err := r.Cookie("session") if err == nil { // Cookie存在,调用主库版本的Home处理 envMaster.Home(w, r) } else { // Cookie不存在,调用从库版本的Home处理 envSlave.Home(w, r) } })
这个方式简单直接,不需要额外的封装,适合快速实现你的需求。
2. 更灵活:抽成可复用的中间件
如果以后有多个路由需要类似的“根据Cookie选DB”逻辑,推荐把判断逻辑抽成中间件,这样可以复用代码:
// 定义一个中间件函数,接收主库和从库的处理函数,返回新的处理函数 func withDBSelector(masterHandler, slaveHandler http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { _, err := r.Cookie("session") if err == nil { masterHandler(w, r) } else { slaveHandler(w, r) } } } // 注册路由时使用中间件 http.HandleFunc("/home", withDBSelector(envMaster.Home, envSlave.Home)) // 其他需要的路由也可以复用 http.HandleFunc("/dashboard", withDBSelector(envMaster.Dashboard, envSlave.Dashboard))
这种方式更符合Go的Web开发习惯,代码复用性更强。
3. 结合你已封装的DB结构体优化
你已经给DB实现了CheckSessionCookie方法,可以稍微调整一下这个方法让它更实用(比如去掉不需要的w参数,直接返回是否存在有效Cookie):
// 优化你的DB方法,只检查Cookie是否存在(如果需要验证合法性,这里可以加逻辑) func (d *DB) HasValidSession(r *http.Request) bool { c, err := r.Cookie("session") if err != nil { return false } // 这里可以额外验证Cookie的有效性,比如去DB查session是否合法 // 比如:return d.validateSession(c.Value) return true }
然后在路由处理里使用这个方法:
http.HandleFunc("/home", func(w http.ResponseWriter, r *http.Request) { if envMaster.HasValidSession(r) { envMaster.Home(w, r) } else { envSlave.Home(w, r) } })
为什么不推荐你之前的方案?
你提到的用/home/:session路由让前端传参数的方式有几个问题:
- 如果Cookie设置了
HttpOnly,前端JavaScript根本无法读取到Cookie,自然没法传递参数; - 把session放到URL里非常不安全,容易被日志记录、缓存或者泄露;
- 不符合URL的设计规范,session属于请求的上下文信息,不应该出现在URL路径里。
额外注意点
建议不要只判断Cookie是否存在,最好还要验证Cookie的有效性(比如去主库查询这个session是否合法、未过期),避免攻击者伪造Cookie获取主库权限。
内容的提问来源于stack exchange,提问作者nohup
相关产品推荐
相关产品推荐

