mirror of
https://github.com/astaxie/beego.git
synced 2025-07-30 00:55:30 +00:00
Merge pull request #4137 from phiphi282/change_redis_provider
Add additional options to redis session prov
This commit is contained in:
@@ -41,7 +41,7 @@ import (
|
||||
|
||||
"github.com/astaxie/beego/pkg/session"
|
||||
|
||||
"github.com/gomodule/redigo/redis"
|
||||
"github.com/go-redis/redis/v7"
|
||||
)
|
||||
|
||||
var redispder = &Provider{}
|
||||
@@ -51,7 +51,7 @@ var MaxPoolSize = 100
|
||||
|
||||
// SessionStore redis session store
|
||||
type SessionStore struct {
|
||||
p *redis.Pool
|
||||
p *redis.Client
|
||||
sid string
|
||||
lock sync.RWMutex
|
||||
values map[interface{}]interface{}
|
||||
@@ -103,19 +103,21 @@ func (rs *SessionStore) SessionRelease(w http.ResponseWriter) {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
c := rs.p.Get()
|
||||
defer c.Close()
|
||||
c.Do("SETEX", rs.sid, rs.maxlifetime, string(b))
|
||||
c := rs.p
|
||||
c.Set(rs.sid, string(b), time.Duration(rs.maxlifetime)*time.Second)
|
||||
}
|
||||
|
||||
// Provider redis session provider
|
||||
type Provider struct {
|
||||
maxlifetime int64
|
||||
savePath string
|
||||
poolsize int
|
||||
password string
|
||||
dbNum int
|
||||
poollist *redis.Pool
|
||||
maxlifetime int64
|
||||
savePath string
|
||||
poolsize int
|
||||
password string
|
||||
dbNum int
|
||||
idleTimeout time.Duration
|
||||
idleCheckFrequency time.Duration
|
||||
maxRetries int
|
||||
poollist *redis.Client
|
||||
}
|
||||
|
||||
// SessionInit init redis session
|
||||
@@ -150,52 +152,44 @@ func (rp *Provider) SessionInit(maxlifetime int64, savePath string) error {
|
||||
} else {
|
||||
rp.dbNum = 0
|
||||
}
|
||||
var idleTimeout time.Duration = 0
|
||||
if len(configs) > 4 {
|
||||
timeout, err := strconv.Atoi(configs[4])
|
||||
if err == nil && timeout > 0 {
|
||||
idleTimeout = time.Duration(timeout) * time.Second
|
||||
rp.idleTimeout = time.Duration(timeout) * time.Second
|
||||
}
|
||||
}
|
||||
rp.poollist = &redis.Pool{
|
||||
Dial: func() (redis.Conn, error) {
|
||||
c, err := redis.Dial("tcp", rp.savePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if rp.password != "" {
|
||||
if _, err = c.Do("AUTH", rp.password); err != nil {
|
||||
c.Close()
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
// some redis proxy such as twemproxy is not support select command
|
||||
if rp.dbNum > 0 {
|
||||
_, err = c.Do("SELECT", rp.dbNum)
|
||||
if err != nil {
|
||||
c.Close()
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return c, err
|
||||
},
|
||||
MaxIdle: rp.poolsize,
|
||||
if len(configs) > 5 {
|
||||
checkFrequency, err := strconv.Atoi(configs[5])
|
||||
if err == nil && checkFrequency > 0 {
|
||||
rp.idleCheckFrequency = time.Duration(checkFrequency) * time.Second
|
||||
}
|
||||
}
|
||||
if len(configs) > 6 {
|
||||
retries, err := strconv.Atoi(configs[6])
|
||||
if err == nil && retries > 0 {
|
||||
rp.maxRetries = retries
|
||||
}
|
||||
}
|
||||
|
||||
rp.poollist.IdleTimeout = idleTimeout
|
||||
rp.poollist = redis.NewClient(&redis.Options{
|
||||
Addr: rp.savePath,
|
||||
Password: rp.password,
|
||||
PoolSize: rp.poolsize,
|
||||
DB: rp.dbNum,
|
||||
IdleTimeout: rp.idleTimeout,
|
||||
IdleCheckFrequency: rp.idleCheckFrequency,
|
||||
MaxRetries: rp.maxRetries,
|
||||
})
|
||||
|
||||
return rp.poollist.Get().Err()
|
||||
return rp.poollist.Ping().Err()
|
||||
}
|
||||
|
||||
// SessionRead read redis session by sid
|
||||
func (rp *Provider) SessionRead(sid string) (session.Store, error) {
|
||||
c := rp.poollist.Get()
|
||||
defer c.Close()
|
||||
|
||||
var kv map[interface{}]interface{}
|
||||
|
||||
kvs, err := redis.String(c.Do("GET", sid))
|
||||
if err != nil && err != redis.ErrNil {
|
||||
kvs, err := rp.poollist.Get(sid).Result()
|
||||
if err != nil && err != redis.Nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(kvs) == 0 {
|
||||
@@ -212,10 +206,9 @@ func (rp *Provider) SessionRead(sid string) (session.Store, error) {
|
||||
|
||||
// SessionExist check redis session exist by sid
|
||||
func (rp *Provider) SessionExist(sid string) (bool, error) {
|
||||
c := rp.poollist.Get()
|
||||
defer c.Close()
|
||||
c := rp.poollist
|
||||
|
||||
if existed, err := redis.Int(c.Do("EXISTS", sid)); err != nil || existed == 0 {
|
||||
if existed, err := c.Exists(sid).Result(); err != nil || existed == 0 {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
@@ -223,27 +216,24 @@ func (rp *Provider) SessionExist(sid string) (bool, error) {
|
||||
|
||||
// SessionRegenerate generate new sid for redis session
|
||||
func (rp *Provider) SessionRegenerate(oldsid, sid string) (session.Store, error) {
|
||||
c := rp.poollist.Get()
|
||||
defer c.Close()
|
||||
|
||||
if existed, _ := redis.Int(c.Do("EXISTS", oldsid)); existed == 0 {
|
||||
c := rp.poollist
|
||||
if existed, _ := c.Exists(oldsid).Result(); existed == 0 {
|
||||
// oldsid doesn't exists, set the new sid directly
|
||||
// ignore error here, since if it return error
|
||||
// the existed value will be 0
|
||||
c.Do("SET", sid, "", "EX", rp.maxlifetime)
|
||||
c.Do(c.Context(), "SET", sid, "", "EX", rp.maxlifetime)
|
||||
} else {
|
||||
c.Do("RENAME", oldsid, sid)
|
||||
c.Do("EXPIRE", sid, rp.maxlifetime)
|
||||
c.Rename(oldsid, sid)
|
||||
c.Expire(sid, time.Duration(rp.maxlifetime) * time.Second)
|
||||
}
|
||||
return rp.SessionRead(sid)
|
||||
}
|
||||
|
||||
// SessionDestroy delete redis session by id
|
||||
func (rp *Provider) SessionDestroy(sid string) error {
|
||||
c := rp.poollist.Get()
|
||||
defer c.Close()
|
||||
c := rp.poollist
|
||||
|
||||
c.Do("DEL", sid)
|
||||
c.Del(sid)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
88
pkg/session/redis/sess_redis_test.go
Normal file
88
pkg/session/redis/sess_redis_test.go
Normal file
@@ -0,0 +1,88 @@
|
||||
package redis
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/astaxie/beego/pkg/session"
|
||||
)
|
||||
|
||||
func TestRedis(t *testing.T) {
|
||||
sessionConfig := &session.ManagerConfig{
|
||||
CookieName: "gosessionid",
|
||||
EnableSetCookie: true,
|
||||
Gclifetime: 3600,
|
||||
Maxlifetime: 3600,
|
||||
Secure: false,
|
||||
CookieLifeTime: 3600,
|
||||
ProviderConfig: "127.0.0.1:6379,100,,0,30",
|
||||
}
|
||||
globalSession, err := session.NewManager("redis", sessionConfig)
|
||||
if err != nil {
|
||||
t.Fatal("could not create manager:", err)
|
||||
}
|
||||
|
||||
go globalSession.GC()
|
||||
|
||||
r, _ := http.NewRequest("GET", "/", nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
sess, err := globalSession.SessionStart(w, r)
|
||||
if err != nil {
|
||||
t.Fatal("session start failed:", err)
|
||||
}
|
||||
defer sess.SessionRelease(w)
|
||||
|
||||
// SET AND GET
|
||||
err = sess.Set("username", "astaxie")
|
||||
if err != nil {
|
||||
t.Fatal("set username failed:", err)
|
||||
}
|
||||
username := sess.Get("username")
|
||||
if username != "astaxie" {
|
||||
t.Fatal("get username failed")
|
||||
}
|
||||
|
||||
// DELETE
|
||||
err = sess.Delete("username")
|
||||
if err != nil {
|
||||
t.Fatal("delete username failed:", err)
|
||||
}
|
||||
username = sess.Get("username")
|
||||
if username != nil {
|
||||
t.Fatal("delete username failed")
|
||||
}
|
||||
|
||||
// FLUSH
|
||||
err = sess.Set("username", "astaxie")
|
||||
if err != nil {
|
||||
t.Fatal("set failed:", err)
|
||||
}
|
||||
err = sess.Set("password", "1qaz2wsx")
|
||||
if err != nil {
|
||||
t.Fatal("set failed:", err)
|
||||
}
|
||||
username = sess.Get("username")
|
||||
if username != "astaxie" {
|
||||
t.Fatal("get username failed")
|
||||
}
|
||||
password := sess.Get("password")
|
||||
if password != "1qaz2wsx" {
|
||||
t.Fatal("get password failed")
|
||||
}
|
||||
err = sess.Flush()
|
||||
if err != nil {
|
||||
t.Fatal("flush failed:", err)
|
||||
}
|
||||
username = sess.Get("username")
|
||||
if username != nil {
|
||||
t.Fatal("flush failed")
|
||||
}
|
||||
password = sess.Get("password")
|
||||
if password != nil {
|
||||
t.Fatal("flush failed")
|
||||
}
|
||||
|
||||
sess.SessionRelease(w)
|
||||
}
|
@@ -34,7 +34,7 @@ package redis_cluster
|
||||
|
||||
import (
|
||||
"github.com/astaxie/beego/pkg/session"
|
||||
rediss "github.com/go-redis/redis"
|
||||
rediss "github.com/go-redis/redis/v7"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -107,12 +107,15 @@ func (rs *SessionStore) SessionRelease(w http.ResponseWriter) {
|
||||
|
||||
// Provider redis_cluster session provider
|
||||
type Provider struct {
|
||||
maxlifetime int64
|
||||
savePath string
|
||||
poolsize int
|
||||
password string
|
||||
dbNum int
|
||||
poollist *rediss.ClusterClient
|
||||
maxlifetime int64
|
||||
savePath string
|
||||
poolsize int
|
||||
password string
|
||||
dbNum int
|
||||
idleTimeout time.Duration
|
||||
idleCheckFrequency time.Duration
|
||||
maxRetries int
|
||||
poollist *rediss.ClusterClient
|
||||
}
|
||||
|
||||
// SessionInit init redis_cluster session
|
||||
@@ -147,11 +150,32 @@ func (rp *Provider) SessionInit(maxlifetime int64, savePath string) error {
|
||||
} else {
|
||||
rp.dbNum = 0
|
||||
}
|
||||
if len(configs) > 4 {
|
||||
timeout, err := strconv.Atoi(configs[4])
|
||||
if err == nil && timeout > 0 {
|
||||
rp.idleTimeout = time.Duration(timeout) * time.Second
|
||||
}
|
||||
}
|
||||
if len(configs) > 5 {
|
||||
checkFrequency, err := strconv.Atoi(configs[5])
|
||||
if err == nil && checkFrequency > 0 {
|
||||
rp.idleCheckFrequency = time.Duration(checkFrequency) * time.Second
|
||||
}
|
||||
}
|
||||
if len(configs) > 6 {
|
||||
retries, err := strconv.Atoi(configs[6])
|
||||
if err == nil && retries > 0 {
|
||||
rp.maxRetries = retries
|
||||
}
|
||||
}
|
||||
|
||||
rp.poollist = rediss.NewClusterClient(&rediss.ClusterOptions{
|
||||
Addrs: strings.Split(rp.savePath, ";"),
|
||||
Password: rp.password,
|
||||
PoolSize: rp.poolsize,
|
||||
Addrs: strings.Split(rp.savePath, ";"),
|
||||
Password: rp.password,
|
||||
PoolSize: rp.poolsize,
|
||||
IdleTimeout: rp.idleTimeout,
|
||||
IdleCheckFrequency: rp.idleCheckFrequency,
|
||||
MaxRetries: rp.maxRetries,
|
||||
})
|
||||
return rp.poollist.Ping().Err()
|
||||
}
|
||||
|
@@ -34,7 +34,7 @@ package redis_sentinel
|
||||
|
||||
import (
|
||||
"github.com/astaxie/beego/pkg/session"
|
||||
"github.com/go-redis/redis"
|
||||
"github.com/go-redis/redis/v7"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -107,13 +107,16 @@ func (rs *SessionStore) SessionRelease(w http.ResponseWriter) {
|
||||
|
||||
// Provider redis_sentinel session provider
|
||||
type Provider struct {
|
||||
maxlifetime int64
|
||||
savePath string
|
||||
poolsize int
|
||||
password string
|
||||
dbNum int
|
||||
poollist *redis.Client
|
||||
masterName string
|
||||
maxlifetime int64
|
||||
savePath string
|
||||
poolsize int
|
||||
password string
|
||||
dbNum int
|
||||
idleTimeout time.Duration
|
||||
idleCheckFrequency time.Duration
|
||||
maxRetries int
|
||||
poollist *redis.Client
|
||||
masterName string
|
||||
}
|
||||
|
||||
// SessionInit init redis_sentinel session
|
||||
@@ -157,13 +160,34 @@ func (rp *Provider) SessionInit(maxlifetime int64, savePath string) error {
|
||||
} else {
|
||||
rp.masterName = "mymaster"
|
||||
}
|
||||
if len(configs) > 5 {
|
||||
timeout, err := strconv.Atoi(configs[4])
|
||||
if err == nil && timeout > 0 {
|
||||
rp.idleTimeout = time.Duration(timeout) * time.Second
|
||||
}
|
||||
}
|
||||
if len(configs) > 6 {
|
||||
checkFrequency, err := strconv.Atoi(configs[5])
|
||||
if err == nil && checkFrequency > 0 {
|
||||
rp.idleCheckFrequency = time.Duration(checkFrequency) * time.Second
|
||||
}
|
||||
}
|
||||
if len(configs) > 7 {
|
||||
retries, err := strconv.Atoi(configs[6])
|
||||
if err == nil && retries > 0 {
|
||||
rp.maxRetries = retries
|
||||
}
|
||||
}
|
||||
|
||||
rp.poollist = redis.NewFailoverClient(&redis.FailoverOptions{
|
||||
SentinelAddrs: strings.Split(rp.savePath, ";"),
|
||||
Password: rp.password,
|
||||
PoolSize: rp.poolsize,
|
||||
DB: rp.dbNum,
|
||||
MasterName: rp.masterName,
|
||||
SentinelAddrs: strings.Split(rp.savePath, ";"),
|
||||
Password: rp.password,
|
||||
PoolSize: rp.poolsize,
|
||||
DB: rp.dbNum,
|
||||
MasterName: rp.masterName,
|
||||
IdleTimeout: rp.idleTimeout,
|
||||
IdleCheckFrequency: rp.idleCheckFrequency,
|
||||
MaxRetries: rp.maxRetries,
|
||||
})
|
||||
|
||||
return rp.poollist.Ping().Err()
|
||||
|
Reference in New Issue
Block a user