diff --git a/session/couchbase/sess_couchbase.go b/session/couchbase/sess_couchbase.go index eea9f567..6b0ffc50 100644 --- a/session/couchbase/sess_couchbase.go +++ b/session/couchbase/sess_couchbase.go @@ -20,8 +20,10 @@ // // Usage: // import( -// _ "github.com/beego/beego/session/couchbase" -// "github.com/beego/beego/session" +// +// _ "github.com/beego/beego/session/couchbase" +// "github.com/beego/beego/session" +// // ) // // func init() { @@ -113,6 +115,12 @@ func (cs *SessionStore) SessionRelease(w http.ResponseWriter) { cs.b.Set(cs.sid, int(cs.maxlifetime), bo) } +// SessionReleaseIfPresent is not supported now. +// If we want to use couchbase, we may refactor the code to use couchbase collection. +func (cs *SessionStore) SessionReleaseIfPresent(w http.ResponseWriter) { + cs.SessionRelease(w) +} + func (cp *Provider) getBucket() *couchbase.Bucket { c, err := couchbase.Connect(cp.savePath) if err != nil { diff --git a/session/ledis/ledis_session.go b/session/ledis/ledis_session.go index 98e6b627..6e706e4e 100644 --- a/session/ledis/ledis_session.go +++ b/session/ledis/ledis_session.go @@ -75,6 +75,13 @@ func (ls *SessionStore) SessionRelease(w http.ResponseWriter) { c.Expire([]byte(ls.sid), ls.maxlifetime) } +// SessionReleaseIfPresent is not supported now, because ledis has no this feature like SETXX or atomic operation. +// https://github.com/ledisdb/ledisdb/issues/251 +// https://github.com/ledisdb/ledisdb/issues/351 +func (ls *SessionStore) SessionReleaseIfPresent(w http.ResponseWriter) { + ls.SessionRelease(w) +} + // Provider ledis session provider type Provider struct { maxlifetime int64 @@ -141,8 +148,8 @@ func (lp *Provider) SessionExist(sid string) bool { func (lp *Provider) SessionRegenerate(oldsid, sid string) (session.Store, error) { count, _ := c.Exists([]byte(sid)) if count == 0 { - // oldsid doesn't exists, set the new sid directly - // ignore error here, since if it return error + // oldsid doesn't exist, set the new sid directly + // ignore error here, since if it returns error // the existed value will be 0 c.Set([]byte(sid), []byte("")) c.Expire([]byte(sid), lp.maxlifetime) @@ -160,7 +167,7 @@ func (lp *Provider) SessionDestroy(sid string) error { return nil } -// SessionGC Impelment method, no used. +// SessionGC Implement method, no used. func (lp *Provider) SessionGC() { } diff --git a/session/memcache/sess_memcache.go b/session/memcache/sess_memcache.go index 3d529173..6d8747c4 100644 --- a/session/memcache/sess_memcache.go +++ b/session/memcache/sess_memcache.go @@ -20,8 +20,10 @@ // // Usage: // import( -// _ "github.com/beego/beego/session/memcache" -// "github.com/beego/beego/session" +// +// _ "github.com/beego/beego/session/memcache" +// "github.com/beego/beego/session" +// // ) // // func init() { @@ -94,12 +96,28 @@ func (rs *SessionStore) SessionID() string { // SessionRelease save session values to memcache func (rs *SessionStore) SessionRelease(w http.ResponseWriter) { - b, err := session.EncodeGob(rs.values) + rs.releaseSession(w, false) +} + +// SessionReleaseIfPresent save session values to memcache when key is present +func (rs *SessionStore) SessionReleaseIfPresent(w http.ResponseWriter) { + rs.releaseSession(w, true) +} + +func (rs *SessionStore) releaseSession(_ http.ResponseWriter, requirePresent bool) { + rs.lock.RLock() + values := rs.values + rs.lock.RUnlock() + b, err := session.EncodeGob(values) if err != nil { return } item := memcache.Item{Key: rs.sid, Value: b, Expiration: int32(rs.maxlifetime)} - client.Set(&item) + if requirePresent { + client.Replace(&item) + } else { + client.Set(&item) + } } // MemProvider memcache session provider @@ -170,8 +188,8 @@ func (rp *MemProvider) SessionRegenerate(oldsid, sid string) (session.Store, err } var contain []byte if item, err := client.Get(sid); err != nil || len(item.Value) == 0 { - // oldsid doesn't exists, set the new sid directly - // ignore error here, since if it return error + // oldsid doesn't exist, set the new sid directly + // ignore error here, since if it returns error // the existed value will be 0 item.Key = sid item.Value = []byte("") diff --git a/session/mysql/sess_mysql.go b/session/mysql/sess_mysql.go index a19f74b5..e4cf9e47 100644 --- a/session/mysql/sess_mysql.go +++ b/session/mysql/sess_mysql.go @@ -19,6 +19,7 @@ // go install github.com/go-sql-driver/mysql // // mysql session support need create table as sql: +// // CREATE TABLE `session` ( // `session_key` char(64) NOT NULL, // `session_data` blob, @@ -28,8 +29,10 @@ // // Usage: // import( -// _ "github.com/beego/beego/session/mysql" -// "github.com/beego/beego/session" +// +// _ "github.com/beego/beego/session/mysql" +// "github.com/beego/beego/session" +// // ) // // func init() { @@ -117,6 +120,11 @@ func (st *SessionStore) SessionRelease(w http.ResponseWriter) { b, time.Now().Unix(), st.sid) } +// SessionReleaseIfPresent save mysql session values to database. +func (st *SessionStore) SessionReleaseIfPresent(w http.ResponseWriter) { + st.SessionRelease(w) +} + // Provider mysql session provider type Provider struct { maxlifetime int64 diff --git a/session/postgres/sess_postgresql.go b/session/postgres/sess_postgresql.go index 366415ee..b407ab4a 100644 --- a/session/postgres/sess_postgresql.go +++ b/session/postgres/sess_postgresql.go @@ -18,7 +18,6 @@ // // go install github.com/lib/pq // -// // needs this table in your database: // // CREATE TABLE session ( @@ -35,11 +34,12 @@ // SessionSavePath = "user=a password=b dbname=c sslmode=disable" // SessionName = session // -// // Usage: // import( -// _ "github.com/beego/beego/session/postgresql" -// "github.com/beego/beego/session" +// +// _ "github.com/beego/beego/session/postgresql" +// "github.com/beego/beego/session" +// // ) // // func init() { @@ -113,15 +113,22 @@ func (st *SessionStore) SessionID() string { // SessionRelease save postgresql session values to database. // must call this method to save values to database. -func (st *SessionStore) SessionRelease(w http.ResponseWriter) { +func (st *SessionStore) SessionRelease(_ http.ResponseWriter) { defer st.c.Close() - b, err := session.EncodeGob(st.values) + st.lock.RLock() + values := st.values + st.lock.RUnlock() + b, err := session.EncodeGob(values) if err != nil { return } st.c.Exec("UPDATE session set session_data=$1, session_expiry=$2 where session_key=$3", b, time.Now().Format(time.RFC3339), st.sid) +} +// SessionReleaseIfPresent save postgresql session values to database when key is present +func (st *SessionStore) SessionReleaseIfPresent(w http.ResponseWriter) { + st.SessionRelease(w) } // Provider postgresql session provider diff --git a/session/redis/sess_redis.go b/session/redis/sess_redis.go index a6aaa287..35ca7c0c 100644 --- a/session/redis/sess_redis.go +++ b/session/redis/sess_redis.go @@ -20,14 +20,16 @@ // // Usage: // import( -// _ "github.com/beego/beego/session/redis" -// "github.com/beego/beego/session" +// +// _ "github.com/beego/beego/session/redis" +// "github.com/beego/beego/session" +// // ) // -// func init() { -// globalSessions, _ = session.NewManager("redis", ``{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"127.0.0.1:7070"}``) -// go globalSessions.GC() -// } +// func init() { +// globalSessions, _ = session.NewManager("redis", ``{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"127.0.0.1:7070"}``) +// go globalSessions.GC() +// } // // more docs: http://beego.me/docs/module/session.md package redis @@ -99,13 +101,28 @@ func (rs *SessionStore) SessionID() string { // SessionRelease save session values to redis func (rs *SessionStore) SessionRelease(w http.ResponseWriter) { - b, err := session.EncodeGob(rs.values) + rs.releaseSession(w, false) +} + +// SessionReleaseIfPresent save session values to redis when key is present +func (rs *SessionStore) SessionReleaseIfPresent(w http.ResponseWriter) { + rs.releaseSession(w, true) +} + +func (rs *SessionStore) releaseSession(_ http.ResponseWriter, requirePresent bool) { + rs.lock.RLock() + values := rs.values + rs.lock.RUnlock() + b, err := session.EncodeGob(values) if err != nil { return } c := rs.p.Get() - defer c.Close() - c.Do("SETEX", rs.sid, rs.maxlifetime, string(b)) + if requirePresent { + c.Do("SETXX", rs.sid, string(b), time.Duration(rs.maxlifetime)*time.Second, "XX") + } else { + c.Do("SETEX", rs.sid, string(b), time.Duration(rs.maxlifetime)*time.Second) + } } // Provider redis session provider @@ -227,8 +244,8 @@ func (rp *Provider) SessionRegenerate(oldsid, sid string) (session.Store, error) defer c.Close() if existed, _ := redis.Int(c.Do("EXISTS", oldsid)); existed == 0 { - // oldsid doesn't exists, set the new sid directly - // ignore error here, since if it return error + // oldsid doesn't exist, set the new sid directly + // ignore error here, since if it returns error // the existed value will be 0 c.Do("SET", sid, "", "EX", rp.maxlifetime) } else { diff --git a/session/redis/session_redis_test.go b/session/redis/session_redis_test.go new file mode 100644 index 00000000..ac671208 --- /dev/null +++ b/session/redis/session_redis_test.go @@ -0,0 +1,148 @@ +package redis + +import ( + "fmt" + "net/http" + "net/http/httptest" + "os" + "sync" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/beego/beego/session" +) + +func TestRedis(t *testing.T) { + globalSession, err := setupSessionManager(t) + if err != nil { + t.Fatal(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) +} + +func TestProvider_SessionInit(t *testing.T) { + savePath := ` +{ "save_path": "my save path", "idle_timeout": "3s"} +` + cp := &Provider{} + cp.SessionInit(12, savePath) + assert.Equal(t, int64(12), cp.maxlifetime) +} + +func TestStoreSessionReleaseIfPresentAndSessionDestroy(t *testing.T) { + globalSessions, err := setupSessionManager(t) + if err != nil { + t.Fatal(err) + } + // todo test if e==nil + go globalSessions.GC() + + r, _ := http.NewRequest("GET", "/", nil) + w := httptest.NewRecorder() + + sess, err := globalSessions.SessionStart(w, r) + if err != nil { + t.Fatal("session start failed:", err) + } + + if err := globalSessions.GetProvider().SessionDestroy(sess.SessionID()); err != nil { + t.Error(err) + return + } + wg := sync.WaitGroup{} + wg.Add(1) + go func() { + defer wg.Done() + sess.SessionReleaseIfPresent(httptest.NewRecorder()) + }() + wg.Wait() + + if globalSessions.GetProvider().SessionExist(sess.SessionID()) { + t.Fatalf("session %s should exist", sess.SessionID()) + } +} + +func setupSessionManager(t *testing.T) (*session.Manager, error) { + redisAddr := os.Getenv("REDIS_ADDR") + if redisAddr == "" { + redisAddr = "127.0.0.1:6379" + } + redisConfig := fmt.Sprintf("%s,100,,0,30", redisAddr) + sessionConfig := &session.ManagerConfig{} + sessionConfig.CookieName = "gosessionid" + sessionConfig.EnableSetCookie = true + sessionConfig.Gclifetime = 3600 + sessionConfig.Maxlifetime = 3600 + sessionConfig.Secure = false + sessionConfig.CookieLifeTime = 3600 + sessionConfig.ProviderConfig = redisConfig + globalSessions, err := session.NewManager("redis", sessionConfig) + if err != nil { + t.Log("could not create manager: ", err) + return nil, err + } + return globalSessions, nil +} diff --git a/session/redis_cluster/redis_cluster.go b/session/redis_cluster/redis_cluster.go index 1f60675c..1c169576 100644 --- a/session/redis_cluster/redis_cluster.go +++ b/session/redis_cluster/redis_cluster.go @@ -20,8 +20,10 @@ // // Usage: // import( -// _ "github.com/beego/beego/session/redis_cluster" -// "github.com/beego/beego/session" +// +// _ "github.com/beego/beego/session/redis_cluster" +// "github.com/beego/beego/session" +// // ) // // func init() { @@ -39,8 +41,9 @@ import ( "sync" "time" - "github.com/beego/beego/session" rediss "github.com/go-redis/redis" + + "github.com/beego/beego/session" ) var redispder = &Provider{} @@ -98,12 +101,28 @@ func (rs *SessionStore) SessionID() string { // SessionRelease save session values to redis_cluster func (rs *SessionStore) SessionRelease(w http.ResponseWriter) { - b, err := session.EncodeGob(rs.values) + rs.releaseSession(w, false) +} + +// SessionReleaseIfPresent save session values to redis_cluster when key is present +func (rs *SessionStore) SessionReleaseIfPresent(w http.ResponseWriter) { + rs.releaseSession(w, true) +} + +func (rs *SessionStore) releaseSession(_ http.ResponseWriter, requirePresent bool) { + rs.lock.RLock() + values := rs.values + rs.lock.RUnlock() + b, err := session.EncodeGob(values) if err != nil { return } c := rs.p - c.Set(rs.sid, string(b), time.Duration(rs.maxlifetime)*time.Second) + if requirePresent { + c.SetXX(rs.sid, string(b), time.Duration(rs.maxlifetime)*time.Second) + } else { + c.Set(rs.sid, string(b), time.Duration(rs.maxlifetime)*time.Second) + } } // Provider redis_cluster session provider @@ -190,8 +209,8 @@ func (rp *Provider) SessionRegenerate(oldsid, sid string) (session.Store, error) c := rp.poollist if existed, err := c.Exists(oldsid).Result(); err != nil || existed == 0 { - // oldsid doesn't exists, set the new sid directly - // ignore error here, since if it return error + // oldsid doesn't exist, set the new sid directly + // ignore error here, since if it returns error // the existed value will be 0 c.Set(sid, "", time.Duration(rp.maxlifetime)*time.Second) } else { diff --git a/session/redis_sentinel/sess_redis_sentinel.go b/session/redis_sentinel/sess_redis_sentinel.go index 4bdd1939..9502f062 100644 --- a/session/redis_sentinel/sess_redis_sentinel.go +++ b/session/redis_sentinel/sess_redis_sentinel.go @@ -20,8 +20,10 @@ // // Usage: // import( -// _ "github.com/beego/beego/session/redis_sentinel" -// "github.com/beego/beego/session" +// +// _ "github.com/beego/beego/session/redis_sentinel" +// "github.com/beego/beego/session" +// // ) // // func init() { @@ -39,8 +41,9 @@ import ( "sync" "time" - "github.com/beego/beego/session" "github.com/go-redis/redis" + + "github.com/beego/beego/session" ) var redispder = &Provider{} @@ -98,12 +101,28 @@ func (rs *SessionStore) SessionID() string { // SessionRelease save session values to redis_sentinel func (rs *SessionStore) SessionRelease(w http.ResponseWriter) { - b, err := session.EncodeGob(rs.values) + rs.releaseSession(w, false) +} + +// SessionReleaseIfPresent save session values to redis_sentinel when key is present +func (rs *SessionStore) SessionReleaseIfPresent(w http.ResponseWriter) { + rs.releaseSession(w, true) +} + +func (rs *SessionStore) releaseSession(_ http.ResponseWriter, requirePresent bool) { + rs.lock.RLock() + values := rs.values + rs.lock.RUnlock() + b, err := session.EncodeGob(values) if err != nil { return } c := rs.p - c.Set(rs.sid, string(b), time.Duration(rs.maxlifetime)*time.Second) + if requirePresent { + c.SetXX(rs.sid, string(b), time.Duration(rs.maxlifetime)*time.Second) + } else { + c.Set(rs.sid, string(b), time.Duration(rs.maxlifetime)*time.Second) + } } // Provider redis_sentinel session provider @@ -203,8 +222,8 @@ func (rp *Provider) SessionRegenerate(oldsid, sid string) (session.Store, error) c := rp.poollist if existed, err := c.Exists(oldsid).Result(); err != nil || existed == 0 { - // oldsid doesn't exists, set the new sid directly - // ignore error here, since if it return error + // oldsid doesn't exist, set the new sid directly + // ignore error here, since if it returns error // the existed value will be 0 c.Set(sid, "", time.Duration(rp.maxlifetime)*time.Second) } else { diff --git a/session/sess_cookie.go b/session/sess_cookie.go index 6ad5debc..c3a9458e 100644 --- a/session/sess_cookie.go +++ b/session/sess_cookie.go @@ -88,6 +88,12 @@ func (st *CookieSessionStore) SessionRelease(w http.ResponseWriter) { } } +// SessionReleaseIfPresent Write cookie session to http response cookie when it is present +// This is a no-op for cookie sessions, because they are always present. +func (st *CookieSessionStore) SessionReleaseIfPresent(w http.ResponseWriter) { + st.SessionRelease(w) +} + type cookieConfig struct { SecurityKey string `json:"securityKey"` BlockKey string `json:"blockKey"` @@ -107,11 +113,12 @@ type CookieProvider struct { // SessionInit Init cookie session provider with max lifetime and config json. // maxlifetime is ignored. // json config: -// securityKey - hash string -// blockKey - gob encode hash string. it's saved as aes crypto. -// securityName - recognized name in encoded cookie string -// cookieName - cookie name -// maxage - cookie max life time. +// +// securityKey - hash string +// blockKey - gob encode hash string. it's saved as aes crypto. +// securityName - recognized name in encoded cookie string +// cookieName - cookie name +// maxage - cookie max life time. func (pder *CookieProvider) SessionInit(maxlifetime int64, config string) error { pder.config = &cookieConfig{} err := json.Unmarshal([]byte(config), pder.config) diff --git a/session/sess_file.go b/session/sess_file.go index 47ad54a7..a743f5f8 100644 --- a/session/sess_file.go +++ b/session/sess_file.go @@ -80,6 +80,15 @@ func (fs *FileSessionStore) SessionID() string { // SessionRelease Write file session to local file with Gob string func (fs *FileSessionStore) SessionRelease(w http.ResponseWriter) { + fs.releaseSession(w, true) +} + +// SessionReleaseIfPresent Write file session to local file with Gob string when session exists +func (fs *FileSessionStore) SessionReleaseIfPresent(w http.ResponseWriter) { + fs.releaseSession(w, false) +} + +func (fs *FileSessionStore) releaseSession(_ http.ResponseWriter, createIfNotExist bool) { filepder.lock.Lock() defer filepder.lock.Unlock() b, err := EncodeGob(fs.values) @@ -87,16 +96,16 @@ func (fs *FileSessionStore) SessionRelease(w http.ResponseWriter) { SLogger.Println(err) return } - _, err = os.Stat(path.Join(filepder.savePath, string(fs.sid[0]), string(fs.sid[1]), fs.sid)) + _, err = os.Stat(filepath.Join(filepder.savePath, string(fs.sid[0]), string(fs.sid[1]), fs.sid)) var f *os.File if err == nil { - f, err = os.OpenFile(path.Join(filepder.savePath, string(fs.sid[0]), string(fs.sid[1]), fs.sid), os.O_RDWR, 0777) + f, err = os.OpenFile(filepath.Join(filepder.savePath, string(fs.sid[0]), string(fs.sid[1]), fs.sid), os.O_RDWR, 0o777) if err != nil { SLogger.Println(err) return } - } else if os.IsNotExist(err) { - f, err = os.Create(path.Join(filepder.savePath, string(fs.sid[0]), string(fs.sid[1]), fs.sid)) + } else if os.IsNotExist(err) && createIfNotExist { + f, err = os.Create(filepath.Join(filepder.savePath, string(fs.sid[0]), string(fs.sid[1]), fs.sid)) if err != nil { SLogger.Println(err) return @@ -221,7 +230,7 @@ func (fp *FileProvider) SessionAll() int { } // SessionRegenerate Generate new sid for file session. -// it delete old file and create new file named from new sid. +// it deletes old file and create new file named from new sid. func (fp *FileProvider) SessionRegenerate(oldsid, sid string) (Store, error) { filepder.lock.Lock() defer filepder.lock.Unlock() diff --git a/session/sess_mem.go b/session/sess_mem.go index 64d8b056..95c7ba04 100644 --- a/session/sess_mem.go +++ b/session/sess_mem.go @@ -75,6 +75,10 @@ func (st *MemSessionStore) SessionID() string { func (st *MemSessionStore) SessionRelease(w http.ResponseWriter) { } +// SessionReleaseIfPresent Implement method, no used. +func (*MemSessionStore) SessionReleaseIfPresent(_ http.ResponseWriter) { +} + // MemProvider Implement the provider interface type MemProvider struct { lock sync.RWMutex // locker diff --git a/session/session.go b/session/session.go index 024c5eef..681d0004 100644 --- a/session/session.go +++ b/session/session.go @@ -16,13 +16,15 @@ // // Usage: // import( -// "github.com/beego/beego/session" +// +// "github.com/beego/beego/session" +// // ) // -// func init() { -// globalSessions, _ = session.NewManager("memory", `{"cookieName":"gosessionid", "enableSetCookie,omitempty": true, "gclifetime":3600, "maxLifetime": 3600, "secure": false, "cookieLifeTime": 3600, "providerConfig": ""}`) -// go globalSessions.GC() -// } +// func init() { +// globalSessions, _ = session.NewManager("memory", `{"cookieName":"gosessionid", "enableSetCookie,omitempty": true, "gclifetime":3600, "maxLifetime": 3600, "secure": false, "cookieLifeTime": 3600, "providerConfig": ""}`) +// go globalSessions.GC() +// } // // more docs: http://beego.me/docs/module/session.md package session @@ -43,12 +45,13 @@ import ( // Store contains all data for one session process with specific id. type Store interface { - Set(key, value interface{}) error //set session value - Get(key interface{}) interface{} //get session value - Delete(key interface{}) error //delete session value - SessionID() string //back current sessionID - SessionRelease(w http.ResponseWriter) // release the resource & save data to provider & return the data - Flush() error //delete all data + Set(key, value interface{}) error // Set set session value + Get(key interface{}) interface{} // Get get session value + Delete(key interface{}) error // Delete delete session value + SessionID() string // SessionID return current sessionID + SessionReleaseIfPresent(w http.ResponseWriter) // SessionReleaseIfPresent release the resource & save data to provider & return the data when the session is present, not all implementation support this feature, you need to check if the specific implementation if support this feature. + SessionRelease(w http.ResponseWriter) // SessionRelease release the resource & save data to provider & return the data + Flush() error // Flush delete all data } // Provider contains global session methods and saved SessionStores. @@ -81,7 +84,7 @@ func Register(name string, provide Provider) { provides[name] = provide } -//GetProvider +// GetProvider func GetProvider(name string) (Provider, error) { provider, ok := provides[name] if !ok { diff --git a/session/ssdb/sess_ssdb.go b/session/ssdb/sess_ssdb.go index cf21bf90..9a675a36 100644 --- a/session/ssdb/sess_ssdb.go +++ b/session/ssdb/sess_ssdb.go @@ -7,8 +7,9 @@ import ( "strings" "sync" - "github.com/beego/beego/session" "github.com/ssdb/gossdb/ssdb" + + "github.com/beego/beego/session" ) var ssdbProvider = &Provider{} @@ -67,7 +68,7 @@ func (p *Provider) SessionRead(sid string) (session.Store, error) { return rs, nil } -// SessionExist judged whether sid is exist in session +// SessionExist judged whether sid is existed in session func (p *Provider) SessionExist(sid string) bool { if p.client == nil { if err := p.connectInit(); err != nil { @@ -194,6 +195,12 @@ func (s *SessionStore) SessionRelease(w http.ResponseWriter) { s.client.Do("setx", s.sid, string(b), s.maxLifetime) } +// SessionReleaseIfPresent is not supported now +// Because ssdb does not support lua script or SETXX command +func (s *SessionStore) SessionReleaseIfPresent(w http.ResponseWriter) { + s.SessionRelease(w) +} + func init() { session.Register("ssdb", ssdbProvider) }