Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Session Go的会话中间件?_Session_Go_Gorilla - Fatal编程技术网

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`对我来说现在看起来更好了。