201 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			201 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package ssdb
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"errors"
 | |
| 	"net/http"
 | |
| 	"strconv"
 | |
| 	"strings"
 | |
| 	"sync"
 | |
| 
 | |
| 	"github.com/astaxie/beego/pkg/infrastructure/session"
 | |
| 	"github.com/ssdb/gossdb/ssdb"
 | |
| )
 | |
| 
 | |
| var ssdbProvider = &Provider{}
 | |
| 
 | |
| // Provider holds ssdb client and configs
 | |
| type Provider struct {
 | |
| 	client      *ssdb.Client
 | |
| 	host        string
 | |
| 	port        int
 | |
| 	maxLifetime int64
 | |
| }
 | |
| 
 | |
| func (p *Provider) connectInit() error {
 | |
| 	var err error
 | |
| 	if p.host == "" || p.port == 0 {
 | |
| 		return errors.New("SessionInit First")
 | |
| 	}
 | |
| 	p.client, err = ssdb.Connect(p.host, p.port)
 | |
| 	return err
 | |
| }
 | |
| 
 | |
| // SessionInit init the ssdb with the config
 | |
| func (p *Provider) SessionInit(ctx context.Context, maxLifetime int64, savePath string) error {
 | |
| 	p.maxLifetime = maxLifetime
 | |
| 	address := strings.Split(savePath, ":")
 | |
| 	p.host = address[0]
 | |
| 
 | |
| 	var err error
 | |
| 	if p.port, err = strconv.Atoi(address[1]); err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	return p.connectInit()
 | |
| }
 | |
| 
 | |
| // SessionRead return a ssdb client session Store
 | |
| func (p *Provider) SessionRead(ctx context.Context, sid string) (session.Store, error) {
 | |
| 	if p.client == nil {
 | |
| 		if err := p.connectInit(); err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 	}
 | |
| 	var kv map[interface{}]interface{}
 | |
| 	value, err := p.client.Get(sid)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if value == nil || len(value.(string)) == 0 {
 | |
| 		kv = make(map[interface{}]interface{})
 | |
| 	} else {
 | |
| 		kv, err = session.DecodeGob([]byte(value.(string)))
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 	}
 | |
| 	rs := &SessionStore{sid: sid, values: kv, maxLifetime: p.maxLifetime, client: p.client}
 | |
| 	return rs, nil
 | |
| }
 | |
| 
 | |
| // SessionExist judged whether sid is exist in session
 | |
| func (p *Provider) SessionExist(ctx context.Context, sid string) (bool, error) {
 | |
| 	if p.client == nil {
 | |
| 		if err := p.connectInit(); err != nil {
 | |
| 			return false, err
 | |
| 		}
 | |
| 	}
 | |
| 	value, err := p.client.Get(sid)
 | |
| 	if err != nil {
 | |
| 		panic(err)
 | |
| 	}
 | |
| 	if value == nil || len(value.(string)) == 0 {
 | |
| 		return false, nil
 | |
| 	}
 | |
| 	return true, nil
 | |
| }
 | |
| 
 | |
| // SessionRegenerate regenerate session with new sid and delete oldsid
 | |
| func (p *Provider) SessionRegenerate(ctx context.Context, oldsid, sid string) (session.Store, error) {
 | |
| 	//conn.Do("setx", key, v, ttl)
 | |
| 	if p.client == nil {
 | |
| 		if err := p.connectInit(); err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 	}
 | |
| 	value, err := p.client.Get(oldsid)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	var kv map[interface{}]interface{}
 | |
| 	if value == nil || len(value.(string)) == 0 {
 | |
| 		kv = make(map[interface{}]interface{})
 | |
| 	} else {
 | |
| 		kv, err = session.DecodeGob([]byte(value.(string)))
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 		_, err = p.client.Del(oldsid)
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 	}
 | |
| 	_, e := p.client.Do("setx", sid, value, p.maxLifetime)
 | |
| 	if e != nil {
 | |
| 		return nil, e
 | |
| 	}
 | |
| 	rs := &SessionStore{sid: sid, values: kv, maxLifetime: p.maxLifetime, client: p.client}
 | |
| 	return rs, nil
 | |
| }
 | |
| 
 | |
| // SessionDestroy destroy the sid
 | |
| func (p *Provider) SessionDestroy(ctx context.Context, sid string) error {
 | |
| 	if p.client == nil {
 | |
| 		if err := p.connectInit(); err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 	}
 | |
| 	_, err := p.client.Del(sid)
 | |
| 	return err
 | |
| }
 | |
| 
 | |
| // SessionGC not implemented
 | |
| func (p *Provider) SessionGC(context.Context) {
 | |
| }
 | |
| 
 | |
| // SessionAll not implemented
 | |
| func (p *Provider) SessionAll(context.Context) int {
 | |
| 	return 0
 | |
| }
 | |
| 
 | |
| // SessionStore holds the session information which stored in ssdb
 | |
| type SessionStore struct {
 | |
| 	sid         string
 | |
| 	lock        sync.RWMutex
 | |
| 	values      map[interface{}]interface{}
 | |
| 	maxLifetime int64
 | |
| 	client      *ssdb.Client
 | |
| }
 | |
| 
 | |
| // Set the key and value
 | |
| func (s *SessionStore) Set(ctx context.Context, key, value interface{}) error {
 | |
| 	s.lock.Lock()
 | |
| 	defer s.lock.Unlock()
 | |
| 	s.values[key] = value
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // Get return the value by the key
 | |
| func (s *SessionStore) Get(ctx context.Context, key interface{}) interface{} {
 | |
| 	s.lock.Lock()
 | |
| 	defer s.lock.Unlock()
 | |
| 	if value, ok := s.values[key]; ok {
 | |
| 		return value
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // Delete the key in session store
 | |
| func (s *SessionStore) Delete(ctx context.Context, key interface{}) error {
 | |
| 	s.lock.Lock()
 | |
| 	defer s.lock.Unlock()
 | |
| 	delete(s.values, key)
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // Flush delete all keys and values
 | |
| func (s *SessionStore) Flush(context.Context) error {
 | |
| 	s.lock.Lock()
 | |
| 	defer s.lock.Unlock()
 | |
| 	s.values = make(map[interface{}]interface{})
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // SessionID return the sessionID
 | |
| func (s *SessionStore) SessionID(context.Context) string {
 | |
| 	return s.sid
 | |
| }
 | |
| 
 | |
| // SessionRelease Store the keyvalues into ssdb
 | |
| func (s *SessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
 | |
| 	b, err := session.EncodeGob(s.values)
 | |
| 	if err != nil {
 | |
| 		return
 | |
| 	}
 | |
| 	s.client.Do("setx", s.sid, string(b), s.maxLifetime)
 | |
| }
 | |
| 
 | |
| func init() {
 | |
| 	session.Register("ssdb", ssdbProvider)
 | |
| }
 |