Session is a special object created by the server to hold user’s state.
Hertz also provides an implementation of Session, which references Gin’s implementation.
Download and install
go get github.com/hertz-contrib/sessions
Import into your code
import "github.com/hertz-contrib/sessions"
package main
import (
"context"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/app/server"
"github.com/cloudwego/hertz/pkg/common/utils"
"github.com/hertz-contrib/sessions"
"github.com/hertz-contrib/sessions/cookie"
)
func main() {
h := server.New(server.WithHostPorts(":8000"))
store := cookie.NewStore([]byte("secret"))
h.Use(sessions.New("mysession", store))
h.GET("/incr", func(ctx context.Context, c *app.RequestContext) {
session := sessions.Default(c)
var count int
v := session.Get("count")
if v != nil {
count = v.(int)
count++
}
session.Set("count", count)
_ = session.Save()
c.JSON(200, utils.H{"count": count})
})
h.Spin()
}
Hertz can configure the Session for a series of operations by using middleware.
The Session
interface defines the main methods to configure the Session operation.
The introduction of the interface methods is as follows:
Note: Session Wraps thinly gorilla-session methods.
Method | Function Signatures | Description |
---|---|---|
ID | ID() string | Used to fetch the Session ID generated by stores, it should not be used for user data. |
Get | Get(key interface{}) interface{} | Used to get the session value associated to the given key. |
Set | Set(key, val interface{}) | Used to set the session value associated to the given key. |
Delete | Delete(key interface{}) | Used to remove the session value associated to the given key. |
Clear | Clear() | Used to delete all values in the session. |
AddFlash | AddFlash(value interface{}, vars ...string) | Used to add a flash message to the session. |
Flashes | Flashes(vars ...string) []interface{} | Used to get a slice of flash messages from the session. |
Options | Options(Options) | Used to set configuration for a session. |
Save | Save() error | Used to save all sessions used during the current request. |
The sessions
middleware provides NewStore
to store sessions in Cookie or Redis.
Function signatures of cookie.NewStore
:
func NewStore(keyPairs ...[]byte) Store
Sample Code:
package main
import (
"context"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/app/server"
"github.com/cloudwego/hertz/pkg/common/utils"
"github.com/hertz-contrib/sessions"
"github.com/hertz-contrib/sessions/cookie"
)
func main() {
h := server.New(server.WithHostPorts(":8000"))
store := cookie.NewStore([]byte("secret"))
h.Use(sessions.New("mysession", store))
h.GET("/incr", func(ctx context.Context, c *app.RequestContext) {
session := sessions.Default(c)
var count int
v := session.Get("count")
if v == nil {
count = 0
} else {
count = v.(int)
count++
}
session.Set("count", count)
_ = session.Save()
c.JSON(200, utils.H{"count": count})
})
h.Spin()
}
Function signatures of redis.NewStore
:
func NewStore(size int, network, addr, passwd string, keyPairs ...[]byte) (Store, error)
Sample Code:
package main
import (
"context"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/app/server"
"github.com/cloudwego/hertz/pkg/common/utils"
"github.com/hertz-contrib/sessions"
"github.com/hertz-contrib/sessions/redis"
)
func main() {
h := server.Default(server.WithHostPorts(":8000"))
store, _ := redis.NewStore(10, "tcp", "localhost:6379", "", []byte("secret"))
h.Use(sessions.New("mysession", store))
h.GET("/incr", func(ctx context.Context, c *app.RequestContext) {
session := sessions.Default(c)
var count int
v := session.Get("count")
if v == nil {
count = 0
} else {
count = v.(int)
count++
}
session.Set("count", count)
session.Save()
c.JSON(200, utils.H{"count": count})
})
h.Spin()
}
The sessions
middleware provides New
to create a single Session.
Function signatures:
func New(name string, store Store) app.HandlerFunc
Sample Code:
package main
import (
"context"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/app/server"
"github.com/cloudwego/hertz/pkg/common/utils"
"github.com/hertz-contrib/sessions"
"github.com/hertz-contrib/sessions/cookie"
)
func main() {
h := server.New(server.WithHostPorts(":8000"))
store := cookie.NewStore([]byte("secret"))
h.Use(sessions.New("mysession", store))
h.GET("/hello", func(ctx context.Context, c *app.RequestContext) {
session := sessions.Default(c)
if session.Get("hello") != "world" {
session.Set("hello", "world")
_ = session.Save()
}
c.JSON(200, utils.H{"hello": session.Get("hello")})
})
h.Spin()
}
The sessions
middleware provides Many
to create multiple sessions.
Function signatures:
func Many(names []string, store Store) app.HandlerFunc
Sample Code:
package main
import (
"context"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/app/server"
"github.com/cloudwego/hertz/pkg/common/utils"
"github.com/hertz-contrib/sessions"
"github.com/hertz-contrib/sessions/cookie"
)
func main() {
h := server.New(server.WithHostPorts(":8000"))
store := cookie.NewStore([]byte("secret"))
sessionNames := []string{"a", "b"}
h.Use(sessions.Many(sessionNames, store))
h.GET("/hello", func(ctx context.Context, c *app.RequestContext) {
sessionA := sessions.DefaultMany(c, "a")
sessionB := sessions.DefaultMany(c, "b")
if sessionA.Get("hello") != "world!" {
sessionA.Set("hello", "world!")
_ = sessionA.Save()
}
if sessionB.Get("hello") != "world?" {
sessionB.Set("hello", "world?")
_ = sessionB.Save()
}
c.JSON(200, utils.H{
"a": sessionA.Get("hello"),
"b": sessionB.Get("hello"),
})
})
h.Spin()
}
The sessions
middleware provides Default
to fetch a single Session.
Function signatures:
func Default(c *app.RequestContext) Session
Sample Code:
package main
import (
"context"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/app/server"
"github.com/cloudwego/hertz/pkg/common/utils"
"github.com/hertz-contrib/sessions"
"github.com/hertz-contrib/sessions/cookie"
)
func main() {
h := server.New(server.WithHostPorts(":8000"))
store := cookie.NewStore([]byte("secret"))
h.Use(sessions.New("mysession", store))
h.GET("/hello", func(ctx context.Context, c *app.RequestContext) {
session := sessions.Default(c)
if session.Get("hello") != "world" {
session.Set("hello", "world")
_ = session.Save()
}
c.JSON(200, utils.H{"hello": session.Get("hello")})
})
h.Spin()
}
The sessions
middleware provides DefaultMany
to get the Session based on its name.
Function signatures:
func DefaultMany(c *app.RequestContext, name string) Session
Sample Code:
package main
import (
"context"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/app/server"
"github.com/cloudwego/hertz/pkg/common/utils"
"github.com/hertz-contrib/sessions"
"github.com/hertz-contrib/sessions/cookie"
)
func main() {
h := server.New(server.WithHostPorts(":8000"))
store := cookie.NewStore([]byte("secret"))
sessionNames := []string{"a", "b"}
h.Use(sessions.Many(sessionNames, store))
h.GET("/hello", func(ctx context.Context, c *app.RequestContext) {
sessionA := sessions.DefaultMany(c, "a")
sessionB := sessions.DefaultMany(c, "b")
if sessionA.Get("hello") != "world!" {
sessionA.Set("hello", "world!")
_ = sessionA.Save()
}
if sessionB.Get("hello") != "world?" {
sessionB.Set("hello", "world?")
_ = sessionB.Save()
}
c.JSON(200, utils.H{
"a": sessionA.Get("hello"),
"b": sessionB.Get("hello"),
})
})
h.Spin()
}
Hertz also provides a bizdemo for distributed session solution based on Redis.
Note: This demo is only a simple demonstration of the distributed session, the specific business code needs to be modified by the user combined with the corresponding business logic
The distributed session solution based on redis is to store the sessions of different servers in redis or redis cluster, which aims to solve the problem that the sessions of multiple servers are not synchronized in the case of distributed system.
Display of core code
// biz/mw/session.go
func InitSession(h *server.Hertz) {
store, err := redis.NewStore(consts.MaxIdleNum, consts.TCP, consts.RedisAddr, consts.RedisPasswd, []byte(consts.SessionSecretKey))
if err != nil {
panic(err)
}
h.Use(sessions.New(consts.HertzSession, store))
}
// biz/handler/user/user_service.go/Login
// ...
session := sessions.Default(c)
session.Set(consts.Username, req.Username)
_ = session.Save()
// ...
// pkg/render/render.go
// ...
session := sessions.Default(c)
username := session.Get(consts.Username)
if username == nil {
// ...
c.Redirect(http.StatusMovedPermanently, []byte("/login.html"))
return
}
// ...
// biz/handler/user/user_service.go/Logout
// ...
session := sessions.Default(c)
session.Delete(consts.Username)
_ = session.Save()
// ...
Session middleware encapsulates most of the complex logic, users only need to call the simple interfaces to complete the corresponding business process.
As for usage, you may refer to example and hertz_session