可以使用alexedwards/scs/v2库将http.ServeHTTP包装起来以添加会话。

huangapple go评论107阅读模式
英文:

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 =&gt; handler
	postRoutes map[string]http.HandlerFunc
	server     http.Server
}
func (s *HttpServer) Run() {
	address := &quot;127.0.0.1:8080&quot;
	s.server = http.Server{
		Addr:           address,
		Handler:        s,
		ReadTimeout:    10 * time.Second,
		WriteTimeout:   10 * time.Second,
		MaxHeaderBytes: 1 &lt;&lt; 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(&quot;/put&quot;, putHandler)
	mux.HandleFunc(&quot;/get&quot;, getHandler)

	// Wrap your handlers with the LoadAndSave() middleware.
	http.ListenAndServe(&quot;:4000&quot;, 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 := &quot;127.0.0.1:8080&quot;
    s.server = http.Server{
        Addr:           address,
        Handler:        sessionManager.LoadAndSave(s),
        ReadTimeout:    10 * time.Second,
        WriteTimeout:   10 * time.Second,
        MaxHeaderBytes: 1 &lt;&lt; 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 := &quot;127.0.0.1:8080&quot;
    
    // 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 (
    &quot;github.com/alexedwards/scs/v2&quot;
    &quot;log&quot;
    &quot;net/http&quot;
    &quot;time&quot;
)

type HttpServer struct {
    getRoutes     map[string]http.HandlerFunc // pattern =&gt; handler
    postRoutes    map[string]http.HandlerFunc
    server        http.Server
    sessionManager *scs.SessionManager
}

func (s *HttpServer) Run(sessionManager *scs.SessionManager) {
    address := &quot;127.0.0.1:8080&quot;
    
    // 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 &lt;&lt; 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 := &amp;HttpServer{
        getRoutes:  make(map[string]http.HandlerFunc),
        postRoutes: make(map[string]http.HandlerFunc),
    }
    
    // Start the server with the session manager
    httpServer.Run(sessionManager)
}

huangapple
  • 本文由 发表于 2023年7月3日 23:31:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/76606201.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定