英文:
Is it possible to wrap http.ServeHttp in go to add sessions using alexedwards/scs/v2
问题
我正在尝试为一个已经用Go语言编写的现有HTTP服务器添加会话功能。我有以下类似的代码:
type HttpServer struct {
getRoutes map[string]http.HandlerFunc // pattern => handler
postRoutes map[string]http.HandlerFunc
server http.Server
}
func (s *HttpServer) Run() {
address := "127.0.0.1:8080"
s.server = http.Server{
Addr: address,
Handler: s,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
MaxHeaderBytes: 1 << 20,
}
log.Fatal(s.server.ListenAndServe())
}
func (s *HttpServer) ServeHTTP(writer http.ResponseWriter, r *http.Request) {
...
}
我想使用 https://pkg.go.dev/github.com/alexedwards/scs/v2#SessionManager.LoadAndSave
来添加会话功能。
链接中的示例代码如下:
mux := http.NewServeMux()
mux.HandleFunc("/put", putHandler)
mux.HandleFunc("/get", getHandler)
// 使用 LoadAndSave() 中间件包装你的处理函数。
http.ListenAndServe(":4000", sessionManager.LoadAndSave(mux))
示例代码将 mux
传递给 LoadAndSave
,然后将新的处理函数传递给 http.ListenAndServe(port, newHandler)
。在我的情况下,处理函数来自我添加到 *HttpServer
结构体中的 ServeHTTP
方法。而示例中的处理函数来自 mux
。
我对Go语言还不熟悉。是否可以将我的 ServeHTTP
方法传递给 LoadAndSave
并使用 LoadAndSave
返回的处理函数?如果不行,是否有一种方法可以将我示例中使用的 http.Server
结构体字段传递给 http.ListenAndServe(Port, handler)
?
英文:
I am trying to add sessions to an existing http server written in go. I have code like the following
type HttpServer struct {
getRoutes map[string]http.HandlerFunc // pattern => handler
postRoutes map[string]http.HandlerFunc
server http.Server
}
func (s *HttpServer) Run() {
address := "127.0.0.1:8080"
s.server = http.Server{
Addr: address,
Handler: s,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
MaxHeaderBytes: 1 << 20,
}
log.Fatal(s.server.ListenAndServe())
}
func (s *HttpServer) ServeHTTP(writer http.ResponseWriter, r *http.Request) {
...
}
I would like to add sessions using
https://pkg.go.dev/github.com/alexedwards/scs/v2#SessionManager.LoadAndSave
The example code in the link is
mux := http.NewServeMux()
mux.HandleFunc("/put", putHandler)
mux.HandleFunc("/get", getHandler)
// Wrap your handlers with the LoadAndSave() middleware.
http.ListenAndServe(":4000", sessionManager.LoadAndSave(mux))
The example code passes mux into LoadAndSave, then passes the new handler into http.ListenAndServe(port, newHandler). In my case the handler comes from a ServeHttp method I added to the *HttpServer struct. The handler in the example case comes from the mux.
I am new to go. Is it possible to pass my ServeHTTP method into LoadAndSave and use the handler returned from LoadAndSave? If not, is there a way to pass the http.Server struct fields used in my example into http.ListenAndServe(Port, handler)?
答案1
得分: 1
是的。*HttpServer实现了http.Handler接口,所以你可以将它传递给LoadAndSave:
func (s *HttpServer) Run() {
address := "127.0.0.1:8080"
s.server = http.Server{
Addr: address,
Handler: sessionManager.LoadAndSave(s),
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
MaxHeaderBytes: 1 << 20,
}
log.Fatal(s.server.ListenAndServe())
}
英文:
Yes. *HttpServer implements the http.Handler interface so you can pass it to LoadAndSave:
func (s *HttpServer) Run() {
address := "127.0.0.1:8080"
s.server = http.Server{
Addr: address,
Handler: sessionManager.LoadAndSave(s),
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
MaxHeaderBytes: 1 << 20,
}
log.Fatal(s.server.ListenAndServe())
}
答案2
得分: 1
如Peter的答案中所述,alexedwards/scs/v2
中的LoadAndSave()
方法期望一个http.Handler
接口作为参数。由于你的HttpServer
类型具有正确签名的ServeHTTP
方法,它满足http.Handler
接口的要求,因此你可以将HttpServer
类型的实例传递给LoadAndSave
方法。
但是你的Run()
方法应该有一个sessionManager *scs.SessionManager
作为参数:
func (s *HttpServer) Run(sessionManager *scs.SessionManager) {
address := "127.0.0.1:8080"
// 使用LoadAndSave中间件包装你的HttpServer。
handlerWithSessions := sessionManager.LoadAndSave(s)
...
}
这意味着你需要在这个方法之外创建和配置SessionManager
(使用scs.New()),并在调用Run
时将其传递进去。在那里,你可以将sessionManager
设置为HttpServer
结构体的字段。这样,你的(s *HttpServer) ServeHTTP(writer http.ResponseWriter, r *http.Request)
方法就可以获取它了。
例如:
package main
import (
"github.com/alexedwards/scs/v2"
"log"
"net/http"
"time"
)
type HttpServer struct {
getRoutes map[string]http.HandlerFunc // pattern => handler
postRoutes map[string]http.HandlerFunc
server http.Server
sessionManager *scs.SessionManager
}
func (s *HttpServer) Run(sessionManager *scs.SessionManager) {
address := "127.0.0.1:8080"
// 设置sessionManager字段
s.sessionManager = sessionManager
// 使用LoadAndSave中间件包装你的HttpServer。
handlerWithSessions := sessionManager.LoadAndSave(s)
s.server = http.Server{
Addr: address,
Handler: handlerWithSessions, // 使用包装后的handler
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
MaxHeaderBytes: 1 << 20,
}
log.Fatal(s.server.ListenAndServe())
}
func (s *HttpServer) ServeHTTP(writer http.ResponseWriter, r *http.Request) {
// 通过sessionManager字段访问session
session := s.sessionManager.Load(r)
// 使用session,例如session.Put、session.Get等
// ...
}
func main() {
// 创建并配置session manager
sessionManager := scs.New()
sessionManager.Lifetime = 24 * time.Hour
// 创建自定义的HttpServer
httpServer := &HttpServer{
getRoutes: make(map[string]http.HandlerFunc),
postRoutes: make(map[string]http.HandlerFunc),
}
// 使用session manager启动服务器
httpServer.Run(sessionManager)
}
英文:
As noted in Peter's answer, the LoadAndSave()
method from alexedwards/scs/v2
expects an http.Handler
interface as an argument.
Since your HttpServer
type has a ServeHTTP
method with the correct signature, it satisfies the http.Handler
interface, and you can pass an instance of your HttpServer
type to the LoadAndSave
method.
But your Run()
method should have a sessionManager *scs.SessionManager
as parameter:
func (s *HttpServer) Run(sessionManager *scs.SessionManager) {
address := "127.0.0.1:8080"
// Wrap your HttpServer with the LoadAndSave middleware.
handlerWithSessions := sessionManager.LoadAndSave(s)
...
}
That means creating and configuring the SessionManager
outside this method (with scs.New()), and passing it in when you call Run
.
There, you can set sessionManager
as a field in the HttpServer
struct.
That will allow your (s *HttpServer) ServeHTTP(writer http.ResponseWriter, r *http.Request)
to retrieve it.
For instance:
package main
import (
"github.com/alexedwards/scs/v2"
"log"
"net/http"
"time"
)
type HttpServer struct {
getRoutes map[string]http.HandlerFunc // pattern => handler
postRoutes map[string]http.HandlerFunc
server http.Server
sessionManager *scs.SessionManager
}
func (s *HttpServer) Run(sessionManager *scs.SessionManager) {
address := "127.0.0.1:8080"
// Set the sessionManager field
s.sessionManager = sessionManager
// Wrap your HttpServer with the LoadAndSave middleware.
handlerWithSessions := sessionManager.LoadAndSave(s)
s.server = http.Server{
Addr: address,
Handler: handlerWithSessions, // Use the wrapped handler
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
MaxHeaderBytes: 1 << 20,
}
log.Fatal(s.server.ListenAndServe())
}
func (s *HttpServer) ServeHTTP(writer http.ResponseWriter, r *http.Request) {
// Access the session via the sessionManager field
session := s.sessionManager.Load(r)
// Use the session, e.g. session.Put, session.Get, etc.
// ...
}
func main() {
// Create and configure the session manager
sessionManager := scs.New()
sessionManager.Lifetime = 24 * time.Hour
// Create your custom HttpServer
httpServer := &HttpServer{
getRoutes: make(map[string]http.HandlerFunc),
postRoutes: make(map[string]http.HandlerFunc),
}
// Start the server with the session manager
httpServer.Run(sessionManager)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论