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

时间:2018-01-20 22:37:39

标签: mysql http go cookies

你好棒的Stackoverflow社区,

为蹩脚的问题道歉。我试图在一段时间内找到这个问题的答案,谷歌搜索并没有帮助我。

我正在使用Go的net/http包,正在关注*sql.Db <{1}}

经过它之后,我试图获得两个*sql.Db类型,一个用于主类型,一个用于从属类型。我的意图是,对于一个简单的路由/home,如果已经设置了session cookie,则使用主连接并让连接转到主服务器并使用RW用户,如果没有,则使用与RO用户的从属连接。我已经在DB上有一个包装器结构*sql.DB,并且附加了一个CheckSessionCookie方法。

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

我的路线看起来像

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

但是,如果请求已设置cookie,我无法想到使用不同处理程序func的优雅方法。我在想,如果我能用javascript读取cookie并将cookie作为参数传递,并将路由用作

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

但我不确定这是否是一种好方法,特别是如果将http only标志设置为cookie。

如果对“/ home”的请求已设置会话cookie,如何使用主连接?

谢谢。

1 个答案:

答案 0 :(得分:2)

一种方法可能是这样的:

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)

    // ...
}

注意: 以下是预告意见,因此不是真正的SO材料。

虽然上面的示例可能对您有用,但我个人认为在Env类型上添加处理程序是一个糟糕的设计决策。如果你有一个有3个,5个或10个路径的小应用程序,它可能没问题,但是如果你需要扩展到更多,比如说50条路线,你最终会得到一个有50多种方法的单一类型,而这些方法可能取决于环境,至少在我看来,环境本身应该在其上定义的行为并不是很明显。

然后还有可能不同的处理程序需要不同的配置类型,或相同的配置类型但具有不同的值,不仅Env现在有50多个方法它还有很多字段几乎没有彼此相同。这也允许处理程序触摸它没有业务接触的东西。

在我看来,Env类型最多应该包含一组值,这些值表示应用程序将要运行的环境,这就是它,没有行为,或者至少不仅仅是谓词和getter实际上有意义作为环境的一部分。