英文:
Best practice with sessions (gorilla/sessions)
问题
在开始使用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,
}
}
Q1:
是否可以在同一域上添加具有不同名称的多个会话?
session1, _ := store.Get(r, "session-name-1")
session2, _ := store.Get(r, "session-name-2")
什么时候需要在同一域上使用多个会话?
Q2:
从会话中获取变量的最佳实践是什么?
my_session_var = session.Values["foo"]
Q3:
如何检查会话是否正确保存?如果同时访问相同的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: 无法将Handler_404(类型为func(http.ResponseWriter, *http.Request, *sessions.Session))转换为类型http.HandlerFunc
英文:
Before starting using sessions in golang I need answers to some questions
session example
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,
}
}
Q1:
Is it possible to add multiple sessions on the same domain with different names?
session1, _ := store.Get(r, "session-name-1")
session2, _ := store.Get(r, "session-name-2")
When do you need multiple sessions on the same domain?
Q2:
What is the best practice to get the variables from the session?
my_session_var = session.Values["foo"]
Q3:
How to check if the session is saved correctly? If you access the same map
to both set and get variables?
update
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!")
}
error
# command-line-arguments
.\mux.go:101: cannot convert Handler_404 (type func(http.ResponseWriter, *http.Request, *sessions.Session)) to type http.HandlerFunc
答案1
得分: 5
《GO的HTTP处理程序的基本扩展》(Simon Whitehead)一文展示了在何时何地定义会话的示例。不必在Handler
本身中定义会话,并且在定义其他处理程序时不必重复大量代码。
通过使用命名类型,您可以定义所需的Handler
:
type handler func(w http.ResponseWriter, r *http.Request, db *mgo.Database)
(在您的情况下,它将是gorilla会话,而不是mgo会话或数据库)
init()
函数可以负责会话创建(这里是mgo会话,但对于其他框架会话,思路是相同的):
func init() {
session, err = mgo.Dial("localhost")
if err != nil {
log.Println(err)
}
}
您可以确保此函数类型(handler
)遵守ServeHTTP()
函数,负责:
- 会话管理(克隆/关闭)
- 调用实际的处理程序(可以有比
w
和r
更多的参数)
func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
s := session.Clone()
defer s.Close()
h(w, r, s.DB("example"))
}
然后,您可以定义实际的Handler
(同样,具有比w
和r
更多的参数):
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
(包括会话)。这样可以使用不同的Handler
,而只需很少的管道,使main()
仅用于声明不同路径(而不是用于初始化会话和处理程序)。
2019年更新:在另一个相关的上下文中,还可以参考“如何处理会话”。
英文:
The article "BASIC EXTENSION OF GO’S HTTP HANDLERS" (Simon Whitehead) shows an example of where and when to define session.
Instead of doing it in the Handler
itself, and having to duplicate a lot of code when you define other Handlers.
With a named type, you can define the Handler
you need:
type handler func(w http.ResponseWriter, r *http.Request, db *mgo.Database)
(in your case, it would be a gorilla sessions instead of a mgo session or database)
The init()
function can take care of the session creation (here mgo session, but the idea is the same for other framework sessions)
func init() {
session, err = mgo.Dial("localhost")
if err != nil {
log.Println(err)
}
}
And you can make sure this function type ('handler
') does respect the ServeHTTP()
function, taking care of:
-
the session management (clone/close)
-
calling your actual handler (which can have more parameters than just
w
andr
)func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { s := session.Clone() defer s.Close() h(w, r, s.DB("example")) }
Then you can define your actual Handler
(again, with more than w
and r
):
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)
}
}
And you can use that handler in your server:
func main() {
mux := http.NewServeMux()
mux.Handle("/", handler(myHandler))
http.ListenAndServe(":8080", mux)
}
The idea is to limit the "plumbing" in main()
to a minimum, while having an Handler
with more parameters (including your session).
That allows you to use different Handlers
with very little plumbing, keeping main()
only for the declaration of the different path (and not for the initialization of session and handlers)
Update 2019: in another related context, see also "How to handle sessions".
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论