【问题标题】:Best practice with sessions (gorilla/sessions)会话的最佳实践(大猩猩/会话)
【发布时间】:2014-11-24 05:27:39
【问题描述】:

在开始在 golang 中使用会话之前,我需要回答一些问题

会话示例

import "github.com/gorilla/sessions"

var store = sessions.NewCookieStore([]byte("33446a9dcf9ea060a0a6532b166da32f304af0de"))

func Handler(w http.ResponseWriter, r *http.Request){
    session, _ := store.Get(r, "session-name")
    
    session.Values["foo"] = "bar"
    session.Values[42] = 43
    session.Save(r, w)
    
    fmt.Fprint(w, "Hello world :)")
}

func main(){
    store.Options = &sessions.Options{
        Domain:     "localhost",
        Path:       "/",
        MaxAge:     60 * 15,
        Secure:     false,
        HttpOnly:   true,
    }
}

第一季度:

是否可以在同一个域上添加多个不同名称的会话?

session1, _ := store.Get(r, "session-name-1")
session2, _ := store.Get(r, "session-name-2")

您何时需要在同一个域上进行多个会话?

第二季度:

从会话中获取变量的最佳做法是什么? my_session_var = session.Values["foo"]

第三季度:

如何检查会话是否正确保存?如果您访问相同的map 来设置和获取变量?

更新

package main

import (
    "github.com/gorilla/sessions"
)

var (
    store = sessions.NewCookieStore([]byte("33446a9dcf9ea060a0a6532b166da32f304af0de"))
)

type handler func(w http.ResponseWriter, r *http.Request, s *sessions.Session)

func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request){
    session, _ := store.Get(r, "session-name")
    
    h(w, r, session)
}

func Handler_404(w http.ResponseWriter, r *http.Request, s *sessions.Session){
    fmt.Fprint(w, "Oops, something went wrong!")
}

错误

# command-line-arguments
.\mux.go:101: cannot convert Handler_404 (type func(http.ResponseWriter, *http.Request, *sessions.Session)) to type http.HandlerFunc

【问题讨论】:

    标签: session go


    【解决方案1】:

    文章“BASIC EXTENSION OF GO’S HTTP HANDLERS”(Simon Whitehead) 展示了在何时何地定义会话的示例。
    而不是在 Handler 本身中执行此操作,并且在定义其他处理程序时必须复制大量代码。

    使用named type,您可以定义您需要的Handler

    type handler func(w http.ResponseWriter, r *http.Request, db *mgo.Database)
    

    (在您的情况下,它将是 gorilla 会话而不是 mgo 会话或数据库)

    init() function 可以处理会话创建(这里是 mgo 会话,但其他框架会话的想法相同)

    func init() {
        session, err = mgo.Dial("localhost")
    
        if err != nil {
            log.Println(err)
        }
    }
    

    您可以确保此函数类型 ('handler') 确实尊重 ServeHTTP() 函数,注意:

    • 会话管理(克隆/关闭)
    • 调用您的实际处理程序(它可以有更多的参数,而不仅仅是 wr

      func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
          s := session.Clone()
          defer s.Close()
      
          h(w, r, s.DB("example"))
      }
      

    然后你可以定义你的实际Handler(同样,不止wr):

    func myHandler(w http.ResponseWriter, r *http.Request, db *mgo.Database) {
        var users []user
    
        db.C("users").Find(nil).All(&users)
    
        for _, user := range users {
            fmt.Fprintf(w, "%s is %d years old", user.Name, user.Age)
        }
    }
    

    您可以在服务器中使用该处理程序:

    func main() {
        mux := http.NewServeMux()
        mux.Handle("/", handler(myHandler))
        http.ListenAndServe(":8080", mux)
    }
    

    这个想法是将main() 中的“管道”限制在最低限度,同时让Handler 具有更多参数(包括您的会话)。
    这允许您使用不同的Handlers,只需很少的管道,保持main() 仅用于声明不同的路径(而不是用于会话和处理程序的初始化)


    2019 年更新:在另一个相关上下文中,另请参阅“How to handle sessions”。

    【讨论】:

    • 更新了我的问题.. 编译时出错
    • @clarkk 最好作为一个单独的问题。
    猜你喜欢
    • 2014-03-15
    • 1970-01-01
    • 1970-01-01
    • 2015-03-30
    • 1970-01-01
    • 2019-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多