Session Go的会话中间件?
我所有的处理程序都使用。如何避免在每个处理程序中存储会话,即代码重复 另一个问题是,是否有更好的方法为模板提供会话值,而不是显式方法,如:Session Go的会话中间件?,session,go,gorilla,Session,Go,Gorilla,我所有的处理程序都使用。如何避免在每个处理程序中存储会话,即代码重复 另一个问题是,是否有更好的方法为模板提供会话值,而不是显式方法,如: func indexHandler(w http.ResponseWriter, req *http.Request) { session, err := store.Get(req, sessionName) if err != nil { log.WithError(err).Error("bad session")
func indexHandler(w http.ResponseWriter, req *http.Request) {
session, err := store.Get(req, sessionName)
if err != nil {
log.WithError(err).Error("bad session")
http.SetCookie(w, &http.Cookie{Name: sessionName, MaxAge: -1, Path: "/"})
}
err = views.ExecuteTemplate(w, "index.html", session.Values)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
代码示例源自对于中间件,您可以定义一个函数,该函数将处理程序作为参数,并返回另一个处理程序作为结果
err = views.ExecuteTemplate(w, "index.html",
struct {
Session map[interface{}]interface{},
...other handler specific data for the template
}{
session.Values,
...
})
返回的处理程序可以存储。获取会话,如果会话不存在,则返回错误;如果会话存在,则将会话存储到请求的上下文中,然后调用实际的处理程序
func sessionMiddleware(h http.HandlerFunc) http.HandlerFunc {
// ...
}
现在,您的处理程序仍然需要从上下文中获取会话值,但是由sessionMiddleware包装的任何处理程序在执行时都可以假定上下文中存在会话,因此可以跳过错误检查
func sessionMiddleware(h http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
session, err := store.Get(r, sessionName)
if err != nil {
log.WithError(err).Error("bad session")
http.SetCookie(w, &http.Cookie{Name: sessionName, MaxAge: -1, Path: "/"})
return
}
r = r.WithContext(context.WithValue(r.Context(), "session", session))
h(w, r)
}
}
要注册处理程序,您需要执行以下操作:
func indexHandler(w http.ResponseWriter, req *http.Request) {
session := req.Context().Value("session").(*sessions.Session)
err := views.ExecuteTemplate(w, "index.html", session.Values)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
func (h SessionHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
session, err := store.Get(r, sessionName)
if err != nil {
log.WithError(err).Error("bad session")
http.SetCookie(w, &http.Cookie{Name: sessionName, MaxAge: -1, Path: "/"})
return
}
h(w, r, session)
}
如果仍然有太多代码重复,您可以直接将会话传递给处理程序,但是您必须更改它们的签名
app.HandleFunc("/", sessionMiddleware(indexHandler))
然后更新处理程序
type SessionHandler func(w http.ResponseWriter, r *http.Request, s *session.Session)
您可以将SessionHandler类型上的中间件部分定义为方法
func indexHandler(w http.ResponseWriter, req *http.Request, s *session.Session) {
err := views.ExecuteTemplate(w, "index.html", s.Values)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
然后要注册处理程序,您需要执行以下操作:
func indexHandler(w http.ResponseWriter, req *http.Request) {
session := req.Context().Value("session").(*sessions.Session)
err := views.ExecuteTemplate(w, "index.html", session.Values)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
func (h SessionHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
session, err := store.Get(r, sessionName)
if err != nil {
log.WithError(err).Error("bad session")
http.SetCookie(w, &http.Cookie{Name: sessionName, MaxAge: -1, Path: "/"})
return
}
h(w, r, session)
}
对于中间件,您可以定义一个函数,该函数将处理程序作为参数,并返回另一个处理程序作为其结果
err = views.ExecuteTemplate(w, "index.html",
struct {
Session map[interface{}]interface{},
...other handler specific data for the template
}{
session.Values,
...
})
返回的处理程序可以存储。获取会话,如果会话不存在,则返回错误;如果会话存在,则将会话存储到请求的上下文中,然后调用实际的处理程序
func sessionMiddleware(h http.HandlerFunc) http.HandlerFunc {
// ...
}
现在,您的处理程序仍然需要从上下文中获取会话值,但是由sessionMiddleware包装的任何处理程序在执行时都可以假定上下文中存在会话,因此可以跳过错误检查
func sessionMiddleware(h http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
session, err := store.Get(r, sessionName)
if err != nil {
log.WithError(err).Error("bad session")
http.SetCookie(w, &http.Cookie{Name: sessionName, MaxAge: -1, Path: "/"})
return
}
r = r.WithContext(context.WithValue(r.Context(), "session", session))
h(w, r)
}
}
要注册处理程序,您需要执行以下操作:
func indexHandler(w http.ResponseWriter, req *http.Request) {
session := req.Context().Value("session").(*sessions.Session)
err := views.ExecuteTemplate(w, "index.html", session.Values)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
func (h SessionHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
session, err := store.Get(r, sessionName)
if err != nil {
log.WithError(err).Error("bad session")
http.SetCookie(w, &http.Cookie{Name: sessionName, MaxAge: -1, Path: "/"})
return
}
h(w, r, session)
}
如果仍然有太多代码重复,您可以直接将会话传递给处理程序,但是您必须更改它们的签名
app.HandleFunc("/", sessionMiddleware(indexHandler))
然后更新处理程序
type SessionHandler func(w http.ResponseWriter, r *http.Request, s *session.Session)
您可以将SessionHandler类型上的中间件部分定义为方法
func indexHandler(w http.ResponseWriter, req *http.Request, s *session.Session) {
err := views.ExecuteTemplate(w, "index.html", s.Values)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
然后要注册处理程序,您需要执行以下操作:
func indexHandler(w http.ResponseWriter, req *http.Request) {
session := req.Context().Value("session").(*sessions.Session)
err := views.ExecuteTemplate(w, "index.html", session.Values)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
func (h SessionHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
session, err := store.Get(r, sessionName)
if err != nil {
log.WithError(err).Error("bad session")
http.SetCookie(w, &http.Cookie{Name: sessionName, MaxAge: -1, Path: "/"})
return
}
h(w, r, session)
}
. 不过,我建议不要这样做。让您的处理程序具有标准的处理程序签名比重复一点更有价值,因为它们保持可组合性。显然,您可以创建一个简单的函数,由需要会话的每个处理程序调用,使其成为一个单行程序。谢谢Peter。是否没有其他方法,例如使用?当然,您可以将会话存储在上下文中。但后来你什么也没得到。会话是从上下文中获取还是从存储中获取并不重要,对吗?。不过,我建议不要这样做。让您的处理程序具有标准的处理程序签名比重复一点更有价值,因为它们保持可组合性。显然,您可以创建一个简单的函数,由需要会话的每个处理程序调用,使其成为一个单行程序。谢谢Peter。是否没有其他方法,例如使用?当然,您可以将会话存储在上下文中。但后来你什么也没得到。不管您是从上下文中获取会话还是从存储中获取会话,对吗?不喜欢更改标准响应、请求签名。因此,`session:=req.Context.Valuesession.*sessions.session`现在在我看来更好了。我不喜欢更改标准的响应、请求签名。所以` session:=req.Context.Valuesession.*sessions.session`对我来说现在看起来更好了。