dongshi6529 2018-01-20 22:37
浏览 50
已采纳

如何使用Go的net / http基于身份验证将请求分发到主从数据库?

Hello awesome Stackoverflow Community,

Apologies for the lame question. I was trying to find an answer to this question for some time, and googling didn't help me much.

I was playing around with Go's net/http package and was following an article on organising *sql.Db

After going through it, I was trying to get two *sql.Dbtypes, one for master and one for slave. My intention was, for a simple route /home, if the sessioncookie is already set, use the master connection and let the connection go to the master server and use an RW user, and if not, use the slave connection with an RO user. I already have a wrapper struct DB over *sql.DB and a CheckSessionCookie method attached to it.

func (d *DB) CheckSessionCookie(w http.ResponseWriter, r *http.Request) (*http.Cookie) {
    c, err := r.Cookie("session")
    if err != nil {
    return nil
    }
    return c
}

My routes looks like

http.HandleFunc("/admin", envMaster.Admin) // Master connection's method
http.HandleFunc("/home", envSlave.Home) // Slave connection's method

However, I cannot think of an elegant way to use a different handler func if the request has a cookie already set. I was thinking, if I could read the cookie with a javascript and pass the cookie as a parameter, and use the route as

http.HandleFunc("/home", envMaster.Home)
http.HandleFunc("/home/:session", envSlave.Home)

But I am not sure if that is a good way to do it, especially if http only flag is set to the cookie.

How do I use a master connection if the request to "/home" has a session cookie already set?

Thank you.

  • 写回答

1条回答 默认 最新

  • duanruanxian5028 2018-01-21 00:59
    关注

    One approach could be something like this:

    type Env struct {
        master *sql.DB
        slave *sql.DB
    }
    
    func (e *Env) DB(r *http.Request) *sql.DB {
        if _, err := r.Cookie("session"); err == http.ErrNoCookie {
                return e.slave
            }
            return e.master
    }
    
    func (e *Env) Home(w http.ResponseWriter, r *http.Request) {
        db := e.DB(r)
    
        // ...
    }
    

    NOTE: The following is a presonal opinion and therefore not really SO material.

    Although the example above may work for you, personally I think that tacking handlers on the Env type is a poor design decision. If you have a tiny app with 3, 5, or 10 routes it may be ok, but if you need to scale to more than that, say 50 routes, you end up with a single type that has 50+ methods and while the methods may depend on the environment it's not really obvious, at least to me, why the environment itself should have behaviour defined on it.

    Then there's also the possibility of different handlers requiring different configuration types, or same configuration types but with different values, not only does Env now have 50+ methods it also has a multitude of fields that have little to nothing in common with each other. This also then allows a handler to touch stuff that it has no business touching.

    In my opinion the Env type should at most comprise a set of values that represent the environment in which the application is gonna run and that's it, no behaviour, or at least no more than mere predicates and getters that actually make sense as being part of the environment.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 R语言Rstudio突然无法启动
  • ¥15 关于#matlab#的问题:提取2个图像的变量作为另外一个图像像元的移动量,计算新的位置创建新的图像并提取第二个图像的变量到新的图像
  • ¥15 改算法,照着压缩包里边,参考其他代码封装的格式 写到main函数里
  • ¥15 用windows做服务的同志有吗
  • ¥60 求一个简单的网页(标签-安全|关键词-上传)
  • ¥35 lstm时间序列共享单车预测,loss值优化,参数优化算法
  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值