mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
MySQL session: fixed problem using mysql as session store, Fixes #1681
This commit is contained in:
parent
4af1dcd54f
commit
7eb45e1799
@ -1,5 +1,7 @@
|
|||||||
# 2.0.0-RC1 (unreleased)
|
# 2.0.0-RC1 (unreleased)
|
||||||
|
|
||||||
|
**FIxes**
|
||||||
|
- [Issue #1681](https://github.com/grafana/grafana/issues/1681). MySQL session: fixed problem using mysql as session store
|
||||||
- [Issue #1671](https://github.com/grafana/grafana/issues/1671). Data sources: Fixed issue with changing default data source (should not require full page load to take effect, now fixed)
|
- [Issue #1671](https://github.com/grafana/grafana/issues/1671). Data sources: Fixed issue with changing default data source (should not require full page load to take effect, now fixed)
|
||||||
|
|
||||||
# 2.0.0-Beta1 (2015-03-30)
|
# 2.0.0-Beta1 (2015-03-30)
|
||||||
|
2
Godeps/Godeps.json
generated
2
Godeps/Godeps.json
generated
@ -47,7 +47,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/macaron-contrib/session",
|
"ImportPath": "github.com/macaron-contrib/session",
|
||||||
"Rev": "65b8817c40cb5bdce08673a15fd2a648c2ba0e16"
|
"Rev": "31e841d95c7302b9ac456c830ea2d6dfcef4f84a"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/mattn/go-sqlite3",
|
"ImportPath": "github.com/mattn/go-sqlite3",
|
||||||
|
2
Godeps/_workspace/src/github.com/macaron-contrib/session/.gitignore
generated
vendored
Normal file
2
Godeps/_workspace/src/github.com/macaron-contrib/session/.gitignore
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
ledis/tmp.db
|
||||||
|
nodb/tmp.db
|
6
Godeps/_workspace/src/github.com/macaron-contrib/session/README.md
generated
vendored
6
Godeps/_workspace/src/github.com/macaron-contrib/session/README.md
generated
vendored
@ -1,7 +1,7 @@
|
|||||||
session [](https://drone.io/github.com/macaron-contrib/session/latest) [](http://gocover.io/github.com/macaron-contrib/session)
|
session [](https://drone.io/github.com/macaron-contrib/session/latest) [](http://gocover.io/github.com/macaron-contrib/session)
|
||||||
=======
|
=======
|
||||||
|
|
||||||
Middleware session provides session management for [Macaron](https://github.com/Unknwon/macaron). It can use many session providers, including memory, file, Redis, Memcache, PostgreSQL, MySQL, Couchbase and Ledis.
|
Middleware session provides session management for [Macaron](https://github.com/Unknwon/macaron). It can use many session providers, including memory, file, Redis, Memcache, PostgreSQL, MySQL, Couchbase, Ledis and Nodb.
|
||||||
|
|
||||||
### Installation
|
### Installation
|
||||||
|
|
||||||
@ -12,6 +12,10 @@ Middleware session provides session management for [Macaron](https://github.com/
|
|||||||
- [API Reference](https://gowalker.org/github.com/macaron-contrib/session)
|
- [API Reference](https://gowalker.org/github.com/macaron-contrib/session)
|
||||||
- [Documentation](http://macaron.gogs.io/docs/middlewares/session)
|
- [Documentation](http://macaron.gogs.io/docs/middlewares/session)
|
||||||
|
|
||||||
|
## Credits
|
||||||
|
|
||||||
|
This package is forked from [beego/session](https://github.com/astaxie/beego/tree/master/session) with reconstruction(over 80%).
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
This project is under Apache v2 License. See the [LICENSE](LICENSE) file for the full license text.
|
This project is under Apache v2 License. See the [LICENSE](LICENSE) file for the full license text.
|
||||||
|
40
Godeps/_workspace/src/github.com/macaron-contrib/session/file.go
generated
vendored
40
Godeps/_workspace/src/github.com/macaron-contrib/session/file.go
generated
vendored
@ -28,17 +28,17 @@ import (
|
|||||||
"github.com/Unknwon/com"
|
"github.com/Unknwon/com"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FileSessionStore represents a file session store implementation.
|
// FileStore represents a file session store implementation.
|
||||||
type FileSessionStore struct {
|
type FileStore struct {
|
||||||
p *FileProvider
|
p *FileProvider
|
||||||
sid string
|
sid string
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
data map[interface{}]interface{}
|
data map[interface{}]interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewFileSessionStore creates and returns a file session store.
|
// NewFileStore creates and returns a file session store.
|
||||||
func NewFileSessionStore(p *FileProvider, sid string, kv map[interface{}]interface{}) *FileSessionStore {
|
func NewFileStore(p *FileProvider, sid string, kv map[interface{}]interface{}) *FileStore {
|
||||||
return &FileSessionStore{
|
return &FileStore{
|
||||||
p: p,
|
p: p,
|
||||||
sid: sid,
|
sid: sid,
|
||||||
data: kv,
|
data: kv,
|
||||||
@ -46,7 +46,7 @@ func NewFileSessionStore(p *FileProvider, sid string, kv map[interface{}]interfa
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set sets value to given key in session.
|
// Set sets value to given key in session.
|
||||||
func (s *FileSessionStore) Set(key, val interface{}) error {
|
func (s *FileStore) Set(key, val interface{}) error {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
defer s.lock.Unlock()
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
@ -55,7 +55,7 @@ func (s *FileSessionStore) Set(key, val interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get gets value by given key in session.
|
// Get gets value by given key in session.
|
||||||
func (s *FileSessionStore) Get(key interface{}) interface{} {
|
func (s *FileStore) Get(key interface{}) interface{} {
|
||||||
s.lock.RLock()
|
s.lock.RLock()
|
||||||
defer s.lock.RUnlock()
|
defer s.lock.RUnlock()
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ func (s *FileSessionStore) Get(key interface{}) interface{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Delete delete a key from session.
|
// Delete delete a key from session.
|
||||||
func (s *FileSessionStore) Delete(key interface{}) error {
|
func (s *FileStore) Delete(key interface{}) error {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
defer s.lock.Unlock()
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
@ -72,12 +72,12 @@ func (s *FileSessionStore) Delete(key interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ID returns current session ID.
|
// ID returns current session ID.
|
||||||
func (s *FileSessionStore) ID() string {
|
func (s *FileStore) ID() string {
|
||||||
return s.sid
|
return s.sid
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release releases resource and save data to provider.
|
// Release releases resource and save data to provider.
|
||||||
func (s *FileSessionStore) Release() error {
|
func (s *FileStore) Release() error {
|
||||||
data, err := EncodeGob(s.data)
|
data, err := EncodeGob(s.data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -87,7 +87,7 @@ func (s *FileSessionStore) Release() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Flush deletes all session data.
|
// Flush deletes all session data.
|
||||||
func (s *FileSessionStore) Flush() error {
|
func (s *FileStore) Flush() error {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
defer s.lock.Unlock()
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
@ -97,7 +97,6 @@ func (s *FileSessionStore) Flush() error {
|
|||||||
|
|
||||||
// FileProvider represents a file session provider implementation.
|
// FileProvider represents a file session provider implementation.
|
||||||
type FileProvider struct {
|
type FileProvider struct {
|
||||||
lock sync.RWMutex
|
|
||||||
maxlifetime int64
|
maxlifetime int64
|
||||||
rootPath string
|
rootPath string
|
||||||
}
|
}
|
||||||
@ -115,9 +114,6 @@ func (p *FileProvider) filepath(sid string) string {
|
|||||||
|
|
||||||
// Read returns raw session store by session ID.
|
// Read returns raw session store by session ID.
|
||||||
func (p *FileProvider) Read(sid string) (_ RawStore, err error) {
|
func (p *FileProvider) Read(sid string) (_ RawStore, err error) {
|
||||||
p.lock.Lock()
|
|
||||||
defer p.lock.Unlock()
|
|
||||||
|
|
||||||
filename := p.filepath(sid)
|
filename := p.filepath(sid)
|
||||||
if err = os.MkdirAll(path.Dir(filename), os.ModePerm); err != nil {
|
if err = os.MkdirAll(path.Dir(filename), os.ModePerm); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -151,22 +147,16 @@ func (p *FileProvider) Read(sid string) (_ RawStore, err error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NewFileSessionStore(p, sid, kv), nil
|
return NewFileStore(p, sid, kv), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exist returns true if session with given ID exists.
|
// Exist returns true if session with given ID exists.
|
||||||
func (p *FileProvider) Exist(sid string) bool {
|
func (p *FileProvider) Exist(sid string) bool {
|
||||||
p.lock.Lock()
|
|
||||||
defer p.lock.Unlock()
|
|
||||||
|
|
||||||
return com.IsFile(p.filepath(sid))
|
return com.IsFile(p.filepath(sid))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destory deletes a session by session ID.
|
// Destory deletes a session by session ID.
|
||||||
func (p *FileProvider) Destory(sid string) error {
|
func (p *FileProvider) Destory(sid string) error {
|
||||||
p.lock.Lock()
|
|
||||||
defer p.lock.Unlock()
|
|
||||||
|
|
||||||
return os.Remove(p.filepath(sid))
|
return os.Remove(p.filepath(sid))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,12 +191,9 @@ func (p *FileProvider) regenerate(oldsid, sid string) (err error) {
|
|||||||
|
|
||||||
// Regenerate regenerates a session store from old session ID to new one.
|
// Regenerate regenerates a session store from old session ID to new one.
|
||||||
func (p *FileProvider) Regenerate(oldsid, sid string) (_ RawStore, err error) {
|
func (p *FileProvider) Regenerate(oldsid, sid string) (_ RawStore, err error) {
|
||||||
p.lock.Lock()
|
|
||||||
if err := p.regenerate(oldsid, sid); err != nil {
|
if err := p.regenerate(oldsid, sid); err != nil {
|
||||||
p.lock.Unlock()
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
p.lock.Unlock()
|
|
||||||
|
|
||||||
return p.Read(sid)
|
return p.Read(sid)
|
||||||
}
|
}
|
||||||
@ -236,9 +223,6 @@ func (p *FileProvider) GC() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
p.lock.Lock()
|
|
||||||
defer p.lock.Unlock()
|
|
||||||
|
|
||||||
if err := filepath.Walk(p.rootPath, func(path string, fi os.FileInfo, err error) error {
|
if err := filepath.Walk(p.rootPath, func(path string, fi os.FileInfo, err error) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
153
Godeps/_workspace/src/github.com/macaron-contrib/session/ledis/ledis.go
generated
vendored
153
Godeps/_workspace/src/github.com/macaron-contrib/session/ledis/ledis.go
generated
vendored
@ -16,26 +16,39 @@
|
|||||||
package session
|
package session
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/Unknwon/com"
|
||||||
"github.com/siddontang/ledisdb/config"
|
"github.com/siddontang/ledisdb/config"
|
||||||
"github.com/siddontang/ledisdb/ledis"
|
"github.com/siddontang/ledisdb/ledis"
|
||||||
|
"gopkg.in/ini.v1"
|
||||||
|
|
||||||
"github.com/macaron-contrib/session"
|
"github.com/macaron-contrib/session"
|
||||||
)
|
)
|
||||||
|
|
||||||
var c *ledis.DB
|
// LedisStore represents a ledis session store implementation.
|
||||||
|
type LedisStore struct {
|
||||||
|
c *ledis.DB
|
||||||
|
sid string
|
||||||
|
expire int64
|
||||||
|
lock sync.RWMutex
|
||||||
|
data map[interface{}]interface{}
|
||||||
|
}
|
||||||
|
|
||||||
// LedisSessionStore represents a ledis session store implementation.
|
// NewLedisStore creates and returns a ledis session store.
|
||||||
type LedisSessionStore struct {
|
func NewLedisStore(c *ledis.DB, sid string, expire int64, kv map[interface{}]interface{}) *LedisStore {
|
||||||
sid string
|
return &LedisStore{
|
||||||
lock sync.RWMutex
|
c: c,
|
||||||
data map[interface{}]interface{}
|
expire: expire,
|
||||||
maxlifetime int64
|
sid: sid,
|
||||||
|
data: kv,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set sets value to given key in session.
|
// Set sets value to given key in session.
|
||||||
func (s *LedisSessionStore) Set(key, val interface{}) error {
|
func (s *LedisStore) Set(key, val interface{}) error {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
defer s.lock.Unlock()
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
@ -44,7 +57,7 @@ func (s *LedisSessionStore) Set(key, val interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get gets value by given key in session.
|
// Get gets value by given key in session.
|
||||||
func (s *LedisSessionStore) Get(key interface{}) interface{} {
|
func (s *LedisStore) Get(key interface{}) interface{} {
|
||||||
s.lock.RLock()
|
s.lock.RLock()
|
||||||
defer s.lock.RUnlock()
|
defer s.lock.RUnlock()
|
||||||
|
|
||||||
@ -52,7 +65,7 @@ func (s *LedisSessionStore) Get(key interface{}) interface{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Delete delete a key from session.
|
// Delete delete a key from session.
|
||||||
func (s *LedisSessionStore) Delete(key interface{}) error {
|
func (s *LedisStore) Delete(key interface{}) error {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
defer s.lock.Unlock()
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
@ -61,25 +74,26 @@ func (s *LedisSessionStore) Delete(key interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ID returns current session ID.
|
// ID returns current session ID.
|
||||||
func (s *LedisSessionStore) ID() string {
|
func (s *LedisStore) ID() string {
|
||||||
return s.sid
|
return s.sid
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release releases resource and save data to provider.
|
// Release releases resource and save data to provider.
|
||||||
func (s *LedisSessionStore) Release() error {
|
func (s *LedisStore) Release() error {
|
||||||
data, err := session.EncodeGob(s.data)
|
data, err := session.EncodeGob(s.data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err = c.Set([]byte(s.sid), data); err != nil {
|
|
||||||
|
if err = s.c.Set([]byte(s.sid), data); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_, err = c.Expire([]byte(s.sid), s.maxlifetime)
|
_, err = s.c.Expire([]byte(s.sid), s.expire)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flush deletes all session data.
|
// Flush deletes all session data.
|
||||||
func (s *LedisSessionStore) Flush() error {
|
func (s *LedisStore) Flush() error {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
defer s.lock.Unlock()
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
@ -89,30 +103,54 @@ func (s *LedisSessionStore) Flush() error {
|
|||||||
|
|
||||||
// LedisProvider represents a ledis session provider implementation.
|
// LedisProvider represents a ledis session provider implementation.
|
||||||
type LedisProvider struct {
|
type LedisProvider struct {
|
||||||
maxlifetime int64
|
c *ledis.DB
|
||||||
savePath string
|
expire int64
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init initializes memory session provider.
|
// Init initializes ledis session provider.
|
||||||
func (p *LedisProvider) Init(maxlifetime int64, savePath string) error {
|
// configs: data_dir=./app.db,db=0
|
||||||
p.maxlifetime = maxlifetime
|
func (p *LedisProvider) Init(expire int64, configs string) error {
|
||||||
p.savePath = savePath
|
p.expire = expire
|
||||||
cfg := new(config.Config)
|
|
||||||
cfg.DataDir = p.savePath
|
cfg, err := ini.Load([]byte(strings.Replace(configs, ",", "\n", -1)))
|
||||||
var err error
|
|
||||||
nowLedis, err := ledis.Open(cfg)
|
|
||||||
c, err = nowLedis.Select(0)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
println(err)
|
return err
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
|
db := 0
|
||||||
|
opt := new(config.Config)
|
||||||
|
for k, v := range cfg.Section("").KeysHash() {
|
||||||
|
switch k {
|
||||||
|
case "data_dir":
|
||||||
|
opt.DataDir = v
|
||||||
|
case "db":
|
||||||
|
db = com.StrTo(v).MustInt()
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("session/ledis: unsupported option '%s'", k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
l, err := ledis.Open(opt)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("session/ledis: error opening db: %v", err)
|
||||||
|
}
|
||||||
|
p.c, err = l.Select(db)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read returns raw session store by session ID.
|
// Read returns raw session store by session ID.
|
||||||
func (p *LedisProvider) Read(sid string) (session.RawStore, error) {
|
func (p *LedisProvider) Read(sid string) (session.RawStore, error) {
|
||||||
kvs, err := c.Get([]byte(sid))
|
if !p.Exist(sid) {
|
||||||
|
if err := p.c.Set([]byte(sid), []byte("")); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var kv map[interface{}]interface{}
|
var kv map[interface{}]interface{}
|
||||||
|
kvs, err := p.c.Get([]byte(sid))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
if len(kvs) == 0 {
|
if len(kvs) == 0 {
|
||||||
kv = make(map[interface{}]interface{})
|
kv = make(map[interface{}]interface{})
|
||||||
} else {
|
} else {
|
||||||
@ -121,41 +159,40 @@ func (p *LedisProvider) Read(sid string) (session.RawStore, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ls := &LedisSessionStore{sid: sid, data: kv, maxlifetime: p.maxlifetime}
|
|
||||||
return ls, nil
|
return NewLedisStore(p.c, sid, p.expire, kv), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exist returns true if session with given ID exists.
|
// Exist returns true if session with given ID exists.
|
||||||
func (p *LedisProvider) Exist(sid string) bool {
|
func (p *LedisProvider) Exist(sid string) bool {
|
||||||
count, _ := c.Exists([]byte(sid))
|
count, err := p.c.Exists([]byte(sid))
|
||||||
if count == 0 {
|
return err == nil && count > 0
|
||||||
return false
|
|
||||||
} else {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destory deletes a session by session ID.
|
// Destory deletes a session by session ID.
|
||||||
func (p *LedisProvider) Destory(sid string) error {
|
func (p *LedisProvider) Destory(sid string) error {
|
||||||
_, err := c.Del([]byte(sid))
|
_, err := p.c.Del([]byte(sid))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Regenerate regenerates a session store from old session ID to new one.
|
// Regenerate regenerates a session store from old session ID to new one.
|
||||||
func (p *LedisProvider) Regenerate(oldsid, sid string) (session.RawStore, error) {
|
func (p *LedisProvider) Regenerate(oldsid, sid string) (_ session.RawStore, err error) {
|
||||||
count, _ := c.Exists([]byte(sid))
|
if p.Exist(sid) {
|
||||||
if count == 0 {
|
return nil, fmt.Errorf("new sid '%s' already exists", sid)
|
||||||
// oldsid doesn't exists, set the new sid directly
|
|
||||||
// ignore error here, since if it return error
|
|
||||||
// the existed value will be 0
|
|
||||||
c.Set([]byte(sid), []byte(""))
|
|
||||||
c.Expire([]byte(sid), p.maxlifetime)
|
|
||||||
} else {
|
|
||||||
data, _ := c.Get([]byte(oldsid))
|
|
||||||
c.Set([]byte(sid), data)
|
|
||||||
c.Expire([]byte(sid), p.maxlifetime)
|
|
||||||
}
|
}
|
||||||
kvs, err := c.Get([]byte(sid))
|
|
||||||
|
kvs := make([]byte, 0)
|
||||||
|
if p.Exist(oldsid) {
|
||||||
|
if kvs, err = p.c.Get([]byte(oldsid)); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else if _, err = p.c.Del([]byte(oldsid)); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err = p.c.SetEX([]byte(sid), p.expire, kvs); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
var kv map[interface{}]interface{}
|
var kv map[interface{}]interface{}
|
||||||
if len(kvs) == 0 {
|
if len(kvs) == 0 {
|
||||||
kv = make(map[interface{}]interface{})
|
kv = make(map[interface{}]interface{})
|
||||||
@ -165,18 +202,20 @@ func (p *LedisProvider) Regenerate(oldsid, sid string) (session.RawStore, error)
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ls := &LedisSessionStore{sid: sid, data: kv, maxlifetime: p.maxlifetime}
|
|
||||||
return ls, nil
|
return NewLedisStore(p.c, sid, p.expire, kv), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count counts and returns number of sessions.
|
// Count counts and returns number of sessions.
|
||||||
func (p *LedisProvider) Count() int {
|
func (p *LedisProvider) Count() int {
|
||||||
// FIXME
|
// FIXME: how come this library does not have DbSize() method?
|
||||||
return 0
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
// GC calls GC to clean expired sessions.
|
// GC calls GC to clean expired sessions.
|
||||||
func (p *LedisProvider) GC() {}
|
func (p *LedisProvider) GC() {
|
||||||
|
// FIXME: wtf???
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
session.Register("ledis", &LedisProvider{})
|
session.Register("ledis", &LedisProvider{})
|
||||||
|
1
Godeps/_workspace/src/github.com/macaron-contrib/session/ledis/ledis.goconvey
generated
vendored
Normal file
1
Godeps/_workspace/src/github.com/macaron-contrib/session/ledis/ledis.goconvey
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
ignore
|
105
Godeps/_workspace/src/github.com/macaron-contrib/session/ledis/ledis_test.go
generated
vendored
Normal file
105
Godeps/_workspace/src/github.com/macaron-contrib/session/ledis/ledis_test.go
generated
vendored
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
// Copyright 2014 Unknwon
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||||
|
// not use this file except in compliance with the License. You may obtain
|
||||||
|
// a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
// License for the specific language governing permissions and limitations
|
||||||
|
// under the License.
|
||||||
|
|
||||||
|
package session
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/Unknwon/macaron"
|
||||||
|
. "github.com/smartystreets/goconvey/convey"
|
||||||
|
|
||||||
|
"github.com/macaron-contrib/session"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_LedisProvider(t *testing.T) {
|
||||||
|
Convey("Test ledis session provider", t, func() {
|
||||||
|
opt := session.Options{
|
||||||
|
Provider: "ledis",
|
||||||
|
ProviderConfig: "data_dir=./tmp.db",
|
||||||
|
}
|
||||||
|
|
||||||
|
Convey("Basic operation", func() {
|
||||||
|
m := macaron.New()
|
||||||
|
m.Use(session.Sessioner(opt))
|
||||||
|
|
||||||
|
m.Get("/", func(ctx *macaron.Context, sess session.Store) {
|
||||||
|
sess.Set("uname", "unknwon")
|
||||||
|
})
|
||||||
|
m.Get("/reg", func(ctx *macaron.Context, sess session.Store) {
|
||||||
|
raw, err := sess.RegenerateId(ctx)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(raw, ShouldNotBeNil)
|
||||||
|
|
||||||
|
uname := raw.Get("uname")
|
||||||
|
So(uname, ShouldNotBeNil)
|
||||||
|
So(uname, ShouldEqual, "unknwon")
|
||||||
|
})
|
||||||
|
m.Get("/get", func(ctx *macaron.Context, sess session.Store) {
|
||||||
|
sid := sess.ID()
|
||||||
|
So(sid, ShouldNotBeEmpty)
|
||||||
|
|
||||||
|
raw, err := sess.Read(sid)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(raw, ShouldNotBeNil)
|
||||||
|
|
||||||
|
uname := sess.Get("uname")
|
||||||
|
So(uname, ShouldNotBeNil)
|
||||||
|
So(uname, ShouldEqual, "unknwon")
|
||||||
|
|
||||||
|
So(sess.Delete("uname"), ShouldBeNil)
|
||||||
|
So(sess.Get("uname"), ShouldBeNil)
|
||||||
|
|
||||||
|
So(sess.Destory(ctx), ShouldBeNil)
|
||||||
|
})
|
||||||
|
|
||||||
|
resp := httptest.NewRecorder()
|
||||||
|
req, err := http.NewRequest("GET", "/", nil)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
m.ServeHTTP(resp, req)
|
||||||
|
|
||||||
|
cookie := resp.Header().Get("Set-Cookie")
|
||||||
|
|
||||||
|
resp = httptest.NewRecorder()
|
||||||
|
req, err = http.NewRequest("GET", "/reg", nil)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
req.Header.Set("Cookie", cookie)
|
||||||
|
m.ServeHTTP(resp, req)
|
||||||
|
|
||||||
|
cookie = resp.Header().Get("Set-Cookie")
|
||||||
|
|
||||||
|
resp = httptest.NewRecorder()
|
||||||
|
req, err = http.NewRequest("GET", "/get", nil)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
req.Header.Set("Cookie", cookie)
|
||||||
|
m.ServeHTTP(resp, req)
|
||||||
|
|
||||||
|
Convey("Regenrate empty session", func() {
|
||||||
|
m.Get("/empty", func(ctx *macaron.Context, sess session.Store) {
|
||||||
|
raw, err := sess.RegenerateId(ctx)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(raw, ShouldNotBeNil)
|
||||||
|
})
|
||||||
|
|
||||||
|
resp = httptest.NewRecorder()
|
||||||
|
req, err = http.NewRequest("GET", "/empty", nil)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
req.Header.Set("Cookie", "MacaronSession=ad2c7e3cbecfcf486; Path=/;")
|
||||||
|
m.ServeHTTP(resp, req)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
210
Godeps/_workspace/src/github.com/macaron-contrib/session/memcache/memcache.go
generated
vendored
210
Godeps/_workspace/src/github.com/macaron-contrib/session/memcache/memcache.go
generated
vendored
@ -16,6 +16,7 @@
|
|||||||
package session
|
package session
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
@ -24,20 +25,35 @@ import (
|
|||||||
"github.com/macaron-contrib/session"
|
"github.com/macaron-contrib/session"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
// MemcacheStore represents a memcache session store implementation.
|
||||||
client *memcache.Client
|
type MemcacheStore struct {
|
||||||
)
|
c *memcache.Client
|
||||||
|
sid string
|
||||||
|
expire int32
|
||||||
|
lock sync.RWMutex
|
||||||
|
data map[interface{}]interface{}
|
||||||
|
}
|
||||||
|
|
||||||
// MemcacheSessionStore represents a memcache session store implementation.
|
// NewMemcacheStore creates and returns a memcache session store.
|
||||||
type MemcacheSessionStore struct {
|
func NewMemcacheStore(c *memcache.Client, sid string, expire int32, kv map[interface{}]interface{}) *MemcacheStore {
|
||||||
sid string
|
return &MemcacheStore{
|
||||||
lock sync.RWMutex
|
c: c,
|
||||||
data map[interface{}]interface{}
|
sid: sid,
|
||||||
maxlifetime int64
|
expire: expire,
|
||||||
|
data: kv,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewItem(sid string, data []byte, expire int32) *memcache.Item {
|
||||||
|
return &memcache.Item{
|
||||||
|
Key: sid,
|
||||||
|
Value: data,
|
||||||
|
Expiration: expire,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set sets value to given key in session.
|
// Set sets value to given key in session.
|
||||||
func (s *MemcacheSessionStore) Set(key, val interface{}) error {
|
func (s *MemcacheStore) Set(key, val interface{}) error {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
defer s.lock.Unlock()
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
@ -46,7 +62,7 @@ func (s *MemcacheSessionStore) Set(key, val interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get gets value by given key in session.
|
// Get gets value by given key in session.
|
||||||
func (s *MemcacheSessionStore) Get(key interface{}) interface{} {
|
func (s *MemcacheStore) Get(key interface{}) interface{} {
|
||||||
s.lock.RLock()
|
s.lock.RLock()
|
||||||
defer s.lock.RUnlock()
|
defer s.lock.RUnlock()
|
||||||
|
|
||||||
@ -54,7 +70,7 @@ func (s *MemcacheSessionStore) Get(key interface{}) interface{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Delete delete a key from session.
|
// Delete delete a key from session.
|
||||||
func (s *MemcacheSessionStore) Delete(key interface{}) error {
|
func (s *MemcacheStore) Delete(key interface{}) error {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
defer s.lock.Unlock()
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
@ -63,26 +79,22 @@ func (s *MemcacheSessionStore) Delete(key interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ID returns current session ID.
|
// ID returns current session ID.
|
||||||
func (s *MemcacheSessionStore) ID() string {
|
func (s *MemcacheStore) ID() string {
|
||||||
return s.sid
|
return s.sid
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release releases resource and save data to provider.
|
// Release releases resource and save data to provider.
|
||||||
func (s *MemcacheSessionStore) Release() error {
|
func (s *MemcacheStore) Release() error {
|
||||||
data, err := session.EncodeGob(s.data)
|
data, err := session.EncodeGob(s.data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return client.Set(&memcache.Item{
|
return s.c.Set(NewItem(s.sid, data, s.expire))
|
||||||
Key: s.sid,
|
|
||||||
Value: data,
|
|
||||||
Expiration: int32(s.maxlifetime),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flush deletes all session data.
|
// Flush deletes all session data.
|
||||||
func (s *MemcacheSessionStore) Flush() error {
|
func (s *MemcacheStore) Flush() error {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
defer s.lock.Unlock()
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
@ -90,41 +102,75 @@ func (s *MemcacheSessionStore) Flush() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// MemProvider represents a memcache session provider implementation.
|
// MemcacheProvider represents a memcache session provider implementation.
|
||||||
type MemProvider struct {
|
type MemcacheProvider struct {
|
||||||
maxlifetime int64
|
c *memcache.Client
|
||||||
conninfo []string
|
expire int32
|
||||||
poolsize int
|
|
||||||
password string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init initializes memory session provider.
|
// Init initializes memcache session provider.
|
||||||
// connStrs can be multiple connection strings separate by ;
|
// connStrs: 127.0.0.1:9090;127.0.0.1:9091
|
||||||
// e.g. 127.0.0.1:9090
|
func (p *MemcacheProvider) Init(expire int64, connStrs string) error {
|
||||||
func (p *MemProvider) Init(maxlifetime int64, connStrs string) error {
|
p.expire = int32(expire)
|
||||||
p.maxlifetime = maxlifetime
|
p.c = memcache.New(strings.Split(connStrs, ";")...)
|
||||||
p.conninfo = strings.Split(connStrs, ";")
|
|
||||||
client = memcache.New(p.conninfo...)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *MemProvider) connectInit() error {
|
|
||||||
client = memcache.New(p.conninfo...)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read returns raw session store by session ID.
|
// Read returns raw session store by session ID.
|
||||||
func (p *MemProvider) Read(sid string) (session.RawStore, error) {
|
func (p *MemcacheProvider) Read(sid string) (session.RawStore, error) {
|
||||||
if client == nil {
|
if !p.Exist(sid) {
|
||||||
if err := p.connectInit(); err != nil {
|
if err := p.c.Set(NewItem(sid, []byte(""), p.expire)); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
item, err := client.Get(sid)
|
var kv map[interface{}]interface{}
|
||||||
|
item, err := p.c.Get(sid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if len(item.Value) == 0 {
|
||||||
|
kv = make(map[interface{}]interface{})
|
||||||
|
} else {
|
||||||
|
kv, err = session.DecodeGob(item.Value)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewMemcacheStore(p.c, sid, p.expire, kv), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exist returns true if session with given ID exists.
|
||||||
|
func (p *MemcacheProvider) Exist(sid string) bool {
|
||||||
|
_, err := p.c.Get(sid)
|
||||||
|
return err == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destory deletes a session by session ID.
|
||||||
|
func (p *MemcacheProvider) Destory(sid string) error {
|
||||||
|
return p.c.Delete(sid)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Regenerate regenerates a session store from old session ID to new one.
|
||||||
|
func (p *MemcacheProvider) Regenerate(oldsid, sid string) (_ session.RawStore, err error) {
|
||||||
|
if p.Exist(sid) {
|
||||||
|
return nil, fmt.Errorf("new sid '%s' already exists", sid)
|
||||||
|
}
|
||||||
|
|
||||||
|
item := NewItem(sid, []byte(""), p.expire)
|
||||||
|
if p.Exist(oldsid) {
|
||||||
|
item, err = p.c.Get(oldsid)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else if err = p.c.Delete(oldsid); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
item.Key = sid
|
||||||
|
}
|
||||||
|
if err = p.c.Set(item); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
var kv map[interface{}]interface{}
|
var kv map[interface{}]interface{}
|
||||||
if len(item.Value) == 0 {
|
if len(item.Value) == 0 {
|
||||||
@ -136,86 +182,18 @@ func (p *MemProvider) Read(sid string) (session.RawStore, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rs := &MemcacheSessionStore{sid: sid, data: kv, maxlifetime: p.maxlifetime}
|
return NewMemcacheStore(p.c, sid, p.expire, kv), nil
|
||||||
return rs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exist returns true if session with given ID exists.
|
|
||||||
func (p *MemProvider) Exist(sid string) bool {
|
|
||||||
if client == nil {
|
|
||||||
if err := p.connectInit(); err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if item, err := client.Get(sid); err != nil || len(item.Value) == 0 {
|
|
||||||
return false
|
|
||||||
} else {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Destory deletes a session by session ID.
|
|
||||||
func (p *MemProvider) Destory(sid string) error {
|
|
||||||
if client == nil {
|
|
||||||
if err := p.connectInit(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return client.Delete(sid)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Regenerate regenerates a session store from old session ID to new one.
|
|
||||||
func (p *MemProvider) Regenerate(oldsid, sid string) (session.RawStore, error) {
|
|
||||||
if client == nil {
|
|
||||||
if err := p.connectInit(); err != nil {
|
|
||||||
return nil, 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
|
|
||||||
// the existed value will be 0
|
|
||||||
item.Key = sid
|
|
||||||
item.Value = []byte("")
|
|
||||||
item.Expiration = int32(p.maxlifetime)
|
|
||||||
client.Set(item)
|
|
||||||
} else {
|
|
||||||
client.Delete(oldsid)
|
|
||||||
item.Key = sid
|
|
||||||
item.Value = item.Value
|
|
||||||
item.Expiration = int32(p.maxlifetime)
|
|
||||||
client.Set(item)
|
|
||||||
contain = item.Value
|
|
||||||
}
|
|
||||||
|
|
||||||
var kv map[interface{}]interface{}
|
|
||||||
if len(contain) == 0 {
|
|
||||||
kv = make(map[interface{}]interface{})
|
|
||||||
} else {
|
|
||||||
var err error
|
|
||||||
kv, err = session.DecodeGob(contain)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rs := &MemcacheSessionStore{sid: sid, data: kv, maxlifetime: p.maxlifetime}
|
|
||||||
return rs, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count counts and returns number of sessions.
|
// Count counts and returns number of sessions.
|
||||||
func (p *MemProvider) Count() int {
|
func (p *MemcacheProvider) Count() int {
|
||||||
// FIXME
|
// FIXME: how come this library does not have Stats method?
|
||||||
return 0
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
// GC calls GC to clean expired sessions.
|
// GC calls GC to clean expired sessions.
|
||||||
func (p *MemProvider) GC() {}
|
func (p *MemcacheProvider) GC() {}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
session.Register("memcache", &MemProvider{})
|
session.Register("memcache", &MemcacheProvider{})
|
||||||
}
|
}
|
||||||
|
1
Godeps/_workspace/src/github.com/macaron-contrib/session/memcache/memcache.goconvey
generated
vendored
Normal file
1
Godeps/_workspace/src/github.com/macaron-contrib/session/memcache/memcache.goconvey
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
ignore
|
107
Godeps/_workspace/src/github.com/macaron-contrib/session/memcache/memcache_test.go
generated
vendored
Normal file
107
Godeps/_workspace/src/github.com/macaron-contrib/session/memcache/memcache_test.go
generated
vendored
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
// Copyright 2014 Unknwon
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||||
|
// not use this file except in compliance with the License. You may obtain
|
||||||
|
// a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
// License for the specific language governing permissions and limitations
|
||||||
|
// under the License.
|
||||||
|
|
||||||
|
package session
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/Unknwon/macaron"
|
||||||
|
. "github.com/smartystreets/goconvey/convey"
|
||||||
|
|
||||||
|
"github.com/macaron-contrib/session"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_MemcacheProvider(t *testing.T) {
|
||||||
|
Convey("Test memcache session provider", t, func() {
|
||||||
|
opt := session.Options{
|
||||||
|
Provider: "memcache",
|
||||||
|
ProviderConfig: "127.0.0.1:9090",
|
||||||
|
}
|
||||||
|
|
||||||
|
Convey("Basic operation", func() {
|
||||||
|
m := macaron.New()
|
||||||
|
m.Use(session.Sessioner(opt))
|
||||||
|
|
||||||
|
m.Get("/", func(ctx *macaron.Context, sess session.Store) {
|
||||||
|
sess.Set("uname", "unknwon")
|
||||||
|
})
|
||||||
|
m.Get("/reg", func(ctx *macaron.Context, sess session.Store) {
|
||||||
|
raw, err := sess.RegenerateId(ctx)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(raw, ShouldNotBeNil)
|
||||||
|
|
||||||
|
uname := raw.Get("uname")
|
||||||
|
So(uname, ShouldNotBeNil)
|
||||||
|
So(uname, ShouldEqual, "unknwon")
|
||||||
|
})
|
||||||
|
m.Get("/get", func(ctx *macaron.Context, sess session.Store) {
|
||||||
|
sid := sess.ID()
|
||||||
|
So(sid, ShouldNotBeEmpty)
|
||||||
|
|
||||||
|
raw, err := sess.Read(sid)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(raw, ShouldNotBeNil)
|
||||||
|
|
||||||
|
uname := sess.Get("uname")
|
||||||
|
So(uname, ShouldNotBeNil)
|
||||||
|
So(uname, ShouldEqual, "unknwon")
|
||||||
|
|
||||||
|
So(sess.Delete("uname"), ShouldBeNil)
|
||||||
|
So(sess.Get("uname"), ShouldBeNil)
|
||||||
|
|
||||||
|
So(sess.Destory(ctx), ShouldBeNil)
|
||||||
|
})
|
||||||
|
|
||||||
|
resp := httptest.NewRecorder()
|
||||||
|
req, err := http.NewRequest("GET", "/", nil)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
m.ServeHTTP(resp, req)
|
||||||
|
|
||||||
|
cookie := resp.Header().Get("Set-Cookie")
|
||||||
|
|
||||||
|
resp = httptest.NewRecorder()
|
||||||
|
req, err = http.NewRequest("GET", "/reg", nil)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
req.Header.Set("Cookie", cookie)
|
||||||
|
m.ServeHTTP(resp, req)
|
||||||
|
|
||||||
|
cookie = resp.Header().Get("Set-Cookie")
|
||||||
|
|
||||||
|
resp = httptest.NewRecorder()
|
||||||
|
req, err = http.NewRequest("GET", "/get", nil)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
req.Header.Set("Cookie", cookie)
|
||||||
|
m.ServeHTTP(resp, req)
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("Regenrate empty session", func() {
|
||||||
|
m := macaron.New()
|
||||||
|
m.Use(session.Sessioner(opt))
|
||||||
|
m.Get("/", func(ctx *macaron.Context, sess session.Store) {
|
||||||
|
raw, err := sess.RegenerateId(ctx)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(raw, ShouldNotBeNil)
|
||||||
|
})
|
||||||
|
|
||||||
|
resp := httptest.NewRecorder()
|
||||||
|
req, err := http.NewRequest("GET", "/", nil)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
req.Header.Set("Cookie", "MacaronSession=ad2c7e3cbecfcf486; Path=/;")
|
||||||
|
m.ServeHTTP(resp, req)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
36
Godeps/_workspace/src/github.com/macaron-contrib/session/memory.go
generated
vendored
36
Godeps/_workspace/src/github.com/macaron-contrib/session/memory.go
generated
vendored
@ -22,17 +22,17 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MemSessionStore represents a in-memory session store implementation.
|
// MemStore represents a in-memory session store implementation.
|
||||||
type MemSessionStore struct {
|
type MemStore struct {
|
||||||
sid string
|
sid string
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
data map[interface{}]interface{}
|
data map[interface{}]interface{}
|
||||||
lastAccess time.Time
|
lastAccess time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMemSessionStore creates and returns a memory session store.
|
// NewMemStore creates and returns a memory session store.
|
||||||
func NewMemSessionStore(sid string) *MemSessionStore {
|
func NewMemStore(sid string) *MemStore {
|
||||||
return &MemSessionStore{
|
return &MemStore{
|
||||||
sid: sid,
|
sid: sid,
|
||||||
data: make(map[interface{}]interface{}),
|
data: make(map[interface{}]interface{}),
|
||||||
lastAccess: time.Now(),
|
lastAccess: time.Now(),
|
||||||
@ -40,7 +40,7 @@ func NewMemSessionStore(sid string) *MemSessionStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set sets value to given key in session.
|
// Set sets value to given key in session.
|
||||||
func (s *MemSessionStore) Set(key, val interface{}) error {
|
func (s *MemStore) Set(key, val interface{}) error {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
defer s.lock.Unlock()
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
@ -49,15 +49,15 @@ func (s *MemSessionStore) Set(key, val interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get gets value by given key in session.
|
// Get gets value by given key in session.
|
||||||
func (s *MemSessionStore) Get(key interface{}) interface{} {
|
func (s *MemStore) Get(key interface{}) interface{} {
|
||||||
s.lock.RLock()
|
s.lock.RLock()
|
||||||
defer s.lock.RUnlock()
|
defer s.lock.RUnlock()
|
||||||
|
|
||||||
return s.data[key]
|
return s.data[key]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete delete a key from session.
|
// Delete deletes a key from session.
|
||||||
func (s *MemSessionStore) Delete(key interface{}) error {
|
func (s *MemStore) Delete(key interface{}) error {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
defer s.lock.Unlock()
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
@ -66,17 +66,17 @@ func (s *MemSessionStore) Delete(key interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ID returns current session ID.
|
// ID returns current session ID.
|
||||||
func (s *MemSessionStore) ID() string {
|
func (s *MemStore) ID() string {
|
||||||
return s.sid
|
return s.sid
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release releases resource and save data to provider.
|
// Release releases resource and save data to provider.
|
||||||
func (_ *MemSessionStore) Release() error {
|
func (_ *MemStore) Release() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flush deletes all session data.
|
// Flush deletes all session data.
|
||||||
func (s *MemSessionStore) Flush() error {
|
func (s *MemStore) Flush() error {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
defer s.lock.Unlock()
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
@ -105,7 +105,7 @@ func (p *MemProvider) update(sid string) error {
|
|||||||
defer p.lock.Unlock()
|
defer p.lock.Unlock()
|
||||||
|
|
||||||
if e, ok := p.data[sid]; ok {
|
if e, ok := p.data[sid]; ok {
|
||||||
e.Value.(*MemSessionStore).lastAccess = time.Now()
|
e.Value.(*MemStore).lastAccess = time.Now()
|
||||||
p.list.MoveToFront(e)
|
p.list.MoveToFront(e)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -122,14 +122,14 @@ func (p *MemProvider) Read(sid string) (_ RawStore, err error) {
|
|||||||
if err = p.update(sid); err != nil {
|
if err = p.update(sid); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return e.Value.(*MemSessionStore), nil
|
return e.Value.(*MemStore), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new session.
|
// Create a new session.
|
||||||
p.lock.Lock()
|
p.lock.Lock()
|
||||||
defer p.lock.Unlock()
|
defer p.lock.Unlock()
|
||||||
|
|
||||||
s := NewMemSessionStore(sid)
|
s := NewMemStore(sid)
|
||||||
p.data[sid] = p.list.PushBack(s)
|
p.data[sid] = p.list.PushBack(s)
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
@ -173,7 +173,7 @@ func (p *MemProvider) Regenerate(oldsid, sid string) (RawStore, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
s.(*MemSessionStore).sid = sid
|
s.(*MemStore).sid = sid
|
||||||
p.data[sid] = p.list.PushBack(s)
|
p.data[sid] = p.list.PushBack(s)
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
@ -193,11 +193,11 @@ func (p *MemProvider) GC() {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.Value.(*MemSessionStore).lastAccess.Unix() + p.maxLifetime) < time.Now().Unix() {
|
if (e.Value.(*MemStore).lastAccess.Unix() + p.maxLifetime) < time.Now().Unix() {
|
||||||
p.lock.RUnlock()
|
p.lock.RUnlock()
|
||||||
p.lock.Lock()
|
p.lock.Lock()
|
||||||
p.list.Remove(e)
|
p.list.Remove(e)
|
||||||
delete(p.data, e.Value.(*MemSessionStore).sid)
|
delete(p.data, e.Value.(*MemStore).sid)
|
||||||
p.lock.Unlock()
|
p.lock.Unlock()
|
||||||
p.lock.RLock()
|
p.lock.RLock()
|
||||||
} else {
|
} else {
|
||||||
|
148
Godeps/_workspace/src/github.com/macaron-contrib/session/mysql/mysql.go
generated
vendored
148
Godeps/_workspace/src/github.com/macaron-contrib/session/mysql/mysql.go
generated
vendored
@ -17,6 +17,8 @@ package session
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -25,16 +27,25 @@ import (
|
|||||||
"github.com/macaron-contrib/session"
|
"github.com/macaron-contrib/session"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MysqlSessionStore represents a mysql session store implementation.
|
// MysqlStore represents a mysql session store implementation.
|
||||||
type MysqlSessionStore struct {
|
type MysqlStore struct {
|
||||||
c *sql.DB
|
c *sql.DB
|
||||||
sid string
|
sid string
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
data map[interface{}]interface{}
|
data map[interface{}]interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewMysqlStore creates and returns a mysql session store.
|
||||||
|
func NewMysqlStore(c *sql.DB, sid string, kv map[interface{}]interface{}) *MysqlStore {
|
||||||
|
return &MysqlStore{
|
||||||
|
c: c,
|
||||||
|
sid: sid,
|
||||||
|
data: kv,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Set sets value to given key in session.
|
// Set sets value to given key in session.
|
||||||
func (s *MysqlSessionStore) Set(key, val interface{}) error {
|
func (s *MysqlStore) Set(key, val interface{}) error {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
defer s.lock.Unlock()
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
@ -43,7 +54,7 @@ func (s *MysqlSessionStore) Set(key, val interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get gets value by given key in session.
|
// Get gets value by given key in session.
|
||||||
func (s *MysqlSessionStore) Get(key interface{}) interface{} {
|
func (s *MysqlStore) Get(key interface{}) interface{} {
|
||||||
s.lock.RLock()
|
s.lock.RLock()
|
||||||
defer s.lock.RUnlock()
|
defer s.lock.RUnlock()
|
||||||
|
|
||||||
@ -51,7 +62,7 @@ func (s *MysqlSessionStore) Get(key interface{}) interface{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Delete delete a key from session.
|
// Delete delete a key from session.
|
||||||
func (s *MysqlSessionStore) Delete(key interface{}) error {
|
func (s *MysqlStore) Delete(key interface{}) error {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
defer s.lock.Unlock()
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
@ -60,24 +71,24 @@ func (s *MysqlSessionStore) Delete(key interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ID returns current session ID.
|
// ID returns current session ID.
|
||||||
func (s *MysqlSessionStore) ID() string {
|
func (s *MysqlStore) ID() string {
|
||||||
return s.sid
|
return s.sid
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release releases resource and save data to provider.
|
// Release releases resource and save data to provider.
|
||||||
func (s *MysqlSessionStore) Release() error {
|
func (s *MysqlStore) Release() error {
|
||||||
defer s.c.Close()
|
|
||||||
data, err := session.EncodeGob(s.data)
|
data, err := session.EncodeGob(s.data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_, err = s.c.Exec("UPDATE session set `session_data`=?, `session_expiry`=? where session_key=?",
|
|
||||||
|
_, err = s.c.Exec("UPDATE session SET data=?, expiry=? WHERE `key`=?",
|
||||||
data, time.Now().Unix(), s.sid)
|
data, time.Now().Unix(), s.sid)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flush deletes all session data.
|
// Flush deletes all session data.
|
||||||
func (s *MysqlSessionStore) Flush() error {
|
func (s *MysqlStore) Flush() error {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
defer s.lock.Unlock()
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
@ -87,113 +98,96 @@ func (s *MysqlSessionStore) Flush() error {
|
|||||||
|
|
||||||
// MysqlProvider represents a mysql session provider implementation.
|
// MysqlProvider represents a mysql session provider implementation.
|
||||||
type MysqlProvider struct {
|
type MysqlProvider struct {
|
||||||
maxlifetime int64
|
c *sql.DB
|
||||||
connStr string
|
expire int64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *MysqlProvider) connectInit() *sql.DB {
|
// Init initializes mysql session provider.
|
||||||
db, e := sql.Open("mysql", p.connStr)
|
// connStr: username:password@protocol(address)/dbname?param=value
|
||||||
if e != nil {
|
func (p *MysqlProvider) Init(expire int64, connStr string) (err error) {
|
||||||
return nil
|
p.expire = expire
|
||||||
|
|
||||||
|
p.c, err = sql.Open("mysql", connStr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
return db
|
return p.c.Ping()
|
||||||
}
|
|
||||||
|
|
||||||
// Init initializes memory session provider.
|
|
||||||
func (p *MysqlProvider) Init(maxlifetime int64, connStr string) error {
|
|
||||||
p.maxlifetime = maxlifetime
|
|
||||||
p.connStr = connStr
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read returns raw session store by session ID.
|
// Read returns raw session store by session ID.
|
||||||
func (p *MysqlProvider) Read(sid string) (session.RawStore, error) {
|
func (p *MysqlProvider) Read(sid string) (session.RawStore, error) {
|
||||||
c := p.connectInit()
|
var data []byte
|
||||||
row := c.QueryRow("select session_data from session where session_key=?", sid)
|
err := p.c.QueryRow("SELECT data FROM session WHERE `key`=?", sid).Scan(&data)
|
||||||
var sessiondata []byte
|
|
||||||
err := row.Scan(&sessiondata)
|
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
c.Exec("insert into session(`session_key`,`session_data`,`session_expiry`) values(?,?,?)",
|
_, err = p.c.Exec("INSERT INTO session(`key`,data,expiry) VALUES(?,?,?)",
|
||||||
sid, "", time.Now().Unix())
|
sid, "", time.Now().Unix())
|
||||||
}
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
var kv map[interface{}]interface{}
|
var kv map[interface{}]interface{}
|
||||||
if len(sessiondata) == 0 {
|
if len(data) == 0 {
|
||||||
kv = make(map[interface{}]interface{})
|
kv = make(map[interface{}]interface{})
|
||||||
} else {
|
} else {
|
||||||
kv, err = session.DecodeGob(sessiondata)
|
kv, err = session.DecodeGob(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rs := &MysqlSessionStore{c: c, sid: sid, data: kv}
|
|
||||||
return rs, nil
|
return NewMysqlStore(p.c, sid, kv), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exist returns true if session with given ID exists.
|
// Exist returns true if session with given ID exists.
|
||||||
func (p *MysqlProvider) Exist(sid string) bool {
|
func (p *MysqlProvider) Exist(sid string) bool {
|
||||||
c := p.connectInit()
|
var data []byte
|
||||||
defer c.Close()
|
err := p.c.QueryRow("SELECT data FROM session WHERE `key`=?", sid).Scan(&data)
|
||||||
|
if err != nil && err != sql.ErrNoRows {
|
||||||
row := c.QueryRow("select session_data from session where session_key=?", sid)
|
panic("session/mysql: error checking existence: " + err.Error())
|
||||||
var sessiondata []byte
|
|
||||||
err := row.Scan(&sessiondata)
|
|
||||||
if err == sql.ErrNoRows {
|
|
||||||
return false
|
|
||||||
} else {
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
return err != sql.ErrNoRows
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destory deletes a session by session ID.
|
// Destory deletes a session by session ID.
|
||||||
func (p *MysqlProvider) Destory(sid string) (err error) {
|
func (p *MysqlProvider) Destory(sid string) error {
|
||||||
c := p.connectInit()
|
_, err := p.c.Exec("DELETE FROM session WHERE `key`=?", sid)
|
||||||
if _, err = c.Exec("DELETE FROM session where session_key=?", sid); err != nil {
|
return err
|
||||||
return err
|
|
||||||
}
|
|
||||||
return c.Close()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Regenerate regenerates a session store from old session ID to new one.
|
// Regenerate regenerates a session store from old session ID to new one.
|
||||||
func (p *MysqlProvider) Regenerate(oldsid, sid string) (session.RawStore, error) {
|
func (p *MysqlProvider) Regenerate(oldsid, sid string) (_ session.RawStore, err error) {
|
||||||
c := p.connectInit()
|
if p.Exist(sid) {
|
||||||
row := c.QueryRow("select session_data from session where session_key=?", oldsid)
|
return nil, fmt.Errorf("new sid '%s' already exists", sid)
|
||||||
var sessiondata []byte
|
|
||||||
err := row.Scan(&sessiondata)
|
|
||||||
if err == sql.ErrNoRows {
|
|
||||||
c.Exec("insert into session(`session_key`,`session_data`,`session_expiry`) values(?,?,?)", oldsid, "", time.Now().Unix())
|
|
||||||
}
|
}
|
||||||
c.Exec("update session set `session_key`=? where session_key=?", sid, oldsid)
|
|
||||||
var kv map[interface{}]interface{}
|
if !p.Exist(oldsid) {
|
||||||
if len(sessiondata) == 0 {
|
if _, err = p.c.Exec("INSERT INTO session(`key`,data,expiry) VALUES(?,?,?)",
|
||||||
kv = make(map[interface{}]interface{})
|
oldsid, "", time.Now().Unix()); err != nil {
|
||||||
} else {
|
|
||||||
kv, err = session.DecodeGob(sessiondata)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rs := &MysqlSessionStore{c: c, sid: sid, data: kv}
|
|
||||||
return rs, nil
|
if _, err = p.c.Exec("UPDATE session SET `key`=? WHERE `key`=?", sid, oldsid); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return p.Read(sid)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count counts and returns number of sessions.
|
// Count counts and returns number of sessions.
|
||||||
func (p *MysqlProvider) Count() int {
|
func (p *MysqlProvider) Count() (total int) {
|
||||||
c := p.connectInit()
|
if err := p.c.QueryRow("SELECT COUNT(*) AS NUM FROM session").Scan(&total); err != nil {
|
||||||
defer c.Close()
|
panic("session/mysql: error counting records: " + err.Error())
|
||||||
|
|
||||||
var total int
|
|
||||||
err := c.QueryRow("SELECT count(*) as num from session").Scan(&total)
|
|
||||||
if err != nil {
|
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
return total
|
return total
|
||||||
}
|
}
|
||||||
|
|
||||||
// GC calls GC to clean expired sessions.
|
// GC calls GC to clean expired sessions.
|
||||||
func (mp *MysqlProvider) GC() {
|
func (p *MysqlProvider) GC() {
|
||||||
c := mp.connectInit()
|
if _, err := p.c.Exec("DELETE FROM session WHERE UNIX_TIMESTAMP(NOW()) - expiry > ?", p.expire); err != nil {
|
||||||
c.Exec("DELETE from session where session_expiry < ?", time.Now().Unix()-mp.maxlifetime)
|
log.Printf("session/mysql: error garbage collecting: %v", err)
|
||||||
c.Close()
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
1
Godeps/_workspace/src/github.com/macaron-contrib/session/mysql/mysql.goconvey
generated
vendored
Normal file
1
Godeps/_workspace/src/github.com/macaron-contrib/session/mysql/mysql.goconvey
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
ignore
|
138
Godeps/_workspace/src/github.com/macaron-contrib/session/mysql/mysql_test.go
generated
vendored
Normal file
138
Godeps/_workspace/src/github.com/macaron-contrib/session/mysql/mysql_test.go
generated
vendored
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
// Copyright 2014 Unknwon
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||||
|
// not use this file except in compliance with the License. You may obtain
|
||||||
|
// a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
// License for the specific language governing permissions and limitations
|
||||||
|
// under the License.
|
||||||
|
|
||||||
|
package session
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/Unknwon/macaron"
|
||||||
|
. "github.com/smartystreets/goconvey/convey"
|
||||||
|
|
||||||
|
"github.com/macaron-contrib/session"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_MysqlProvider(t *testing.T) {
|
||||||
|
Convey("Test mysql session provider", t, func() {
|
||||||
|
opt := session.Options{
|
||||||
|
Provider: "mysql",
|
||||||
|
ProviderConfig: "root:@tcp(localhost:3306)/macaron?charset=utf8",
|
||||||
|
}
|
||||||
|
|
||||||
|
Convey("Basic operation", func() {
|
||||||
|
m := macaron.New()
|
||||||
|
m.Use(session.Sessioner(opt))
|
||||||
|
|
||||||
|
m.Get("/", func(ctx *macaron.Context, sess session.Store) {
|
||||||
|
sess.Set("uname", "unknwon")
|
||||||
|
})
|
||||||
|
m.Get("/reg", func(ctx *macaron.Context, sess session.Store) {
|
||||||
|
raw, err := sess.RegenerateId(ctx)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(raw, ShouldNotBeNil)
|
||||||
|
|
||||||
|
uname := raw.Get("uname")
|
||||||
|
So(uname, ShouldNotBeNil)
|
||||||
|
So(uname, ShouldEqual, "unknwon")
|
||||||
|
})
|
||||||
|
m.Get("/get", func(ctx *macaron.Context, sess session.Store) {
|
||||||
|
sid := sess.ID()
|
||||||
|
So(sid, ShouldNotBeEmpty)
|
||||||
|
|
||||||
|
raw, err := sess.Read(sid)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(raw, ShouldNotBeNil)
|
||||||
|
So(raw.Release(), ShouldBeNil)
|
||||||
|
|
||||||
|
uname := sess.Get("uname")
|
||||||
|
So(uname, ShouldNotBeNil)
|
||||||
|
So(uname, ShouldEqual, "unknwon")
|
||||||
|
|
||||||
|
So(sess.Delete("uname"), ShouldBeNil)
|
||||||
|
So(sess.Get("uname"), ShouldBeNil)
|
||||||
|
|
||||||
|
So(sess.Destory(ctx), ShouldBeNil)
|
||||||
|
})
|
||||||
|
|
||||||
|
resp := httptest.NewRecorder()
|
||||||
|
req, err := http.NewRequest("GET", "/", nil)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
m.ServeHTTP(resp, req)
|
||||||
|
|
||||||
|
cookie := resp.Header().Get("Set-Cookie")
|
||||||
|
|
||||||
|
resp = httptest.NewRecorder()
|
||||||
|
req, err = http.NewRequest("GET", "/reg", nil)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
req.Header.Set("Cookie", cookie)
|
||||||
|
m.ServeHTTP(resp, req)
|
||||||
|
|
||||||
|
cookie = resp.Header().Get("Set-Cookie")
|
||||||
|
|
||||||
|
resp = httptest.NewRecorder()
|
||||||
|
req, err = http.NewRequest("GET", "/get", nil)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
req.Header.Set("Cookie", cookie)
|
||||||
|
m.ServeHTTP(resp, req)
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("Regenrate empty session", func() {
|
||||||
|
m := macaron.New()
|
||||||
|
m.Use(session.Sessioner(opt))
|
||||||
|
m.Get("/", func(ctx *macaron.Context, sess session.Store) {
|
||||||
|
raw, err := sess.RegenerateId(ctx)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(raw, ShouldNotBeNil)
|
||||||
|
|
||||||
|
So(sess.Destory(ctx), ShouldBeNil)
|
||||||
|
})
|
||||||
|
|
||||||
|
resp := httptest.NewRecorder()
|
||||||
|
req, err := http.NewRequest("GET", "/", nil)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
req.Header.Set("Cookie", "MacaronSession=ad2c7e3cbecfcf48; Path=/;")
|
||||||
|
m.ServeHTTP(resp, req)
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("GC session", func() {
|
||||||
|
m := macaron.New()
|
||||||
|
opt2 := opt
|
||||||
|
opt2.Gclifetime = 1
|
||||||
|
m.Use(session.Sessioner(opt2))
|
||||||
|
|
||||||
|
m.Get("/", func(sess session.Store) {
|
||||||
|
sess.Set("uname", "unknwon")
|
||||||
|
So(sess.ID(), ShouldNotBeEmpty)
|
||||||
|
uname := sess.Get("uname")
|
||||||
|
So(uname, ShouldNotBeNil)
|
||||||
|
So(uname, ShouldEqual, "unknwon")
|
||||||
|
|
||||||
|
So(sess.Flush(), ShouldBeNil)
|
||||||
|
So(sess.Get("uname"), ShouldBeNil)
|
||||||
|
|
||||||
|
time.Sleep(2 * time.Second)
|
||||||
|
sess.GC()
|
||||||
|
So(sess.Count(), ShouldEqual, 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
resp := httptest.NewRecorder()
|
||||||
|
req, err := http.NewRequest("GET", "/", nil)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
m.ServeHTTP(resp, req)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
203
Godeps/_workspace/src/github.com/macaron-contrib/session/nodb/nodb.go
generated
vendored
Normal file
203
Godeps/_workspace/src/github.com/macaron-contrib/session/nodb/nodb.go
generated
vendored
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
// Copyright 2015 Unknwon
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||||
|
// not use this file except in compliance with the License. You may obtain
|
||||||
|
// a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
// License for the specific language governing permissions and limitations
|
||||||
|
// under the License.
|
||||||
|
|
||||||
|
package session
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/lunny/nodb"
|
||||||
|
"github.com/lunny/nodb/config"
|
||||||
|
|
||||||
|
"github.com/macaron-contrib/session"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NodbStore represents a nodb session store implementation.
|
||||||
|
type NodbStore struct {
|
||||||
|
c *nodb.DB
|
||||||
|
sid string
|
||||||
|
expire int64
|
||||||
|
lock sync.RWMutex
|
||||||
|
data map[interface{}]interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNodbStore creates and returns a ledis session store.
|
||||||
|
func NewNodbStore(c *nodb.DB, sid string, expire int64, kv map[interface{}]interface{}) *NodbStore {
|
||||||
|
return &NodbStore{
|
||||||
|
c: c,
|
||||||
|
expire: expire,
|
||||||
|
sid: sid,
|
||||||
|
data: kv,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set sets value to given key in session.
|
||||||
|
func (s *NodbStore) Set(key, val interface{}) error {
|
||||||
|
s.lock.Lock()
|
||||||
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
|
s.data[key] = val
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get gets value by given key in session.
|
||||||
|
func (s *NodbStore) Get(key interface{}) interface{} {
|
||||||
|
s.lock.RLock()
|
||||||
|
defer s.lock.RUnlock()
|
||||||
|
|
||||||
|
return s.data[key]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete delete a key from session.
|
||||||
|
func (s *NodbStore) Delete(key interface{}) error {
|
||||||
|
s.lock.Lock()
|
||||||
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
|
delete(s.data, key)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ID returns current session ID.
|
||||||
|
func (s *NodbStore) ID() string {
|
||||||
|
return s.sid
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release releases resource and save data to provider.
|
||||||
|
func (s *NodbStore) Release() error {
|
||||||
|
data, err := session.EncodeGob(s.data)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = s.c.Set([]byte(s.sid), data); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = s.c.Expire([]byte(s.sid), s.expire)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flush deletes all session data.
|
||||||
|
func (s *NodbStore) Flush() error {
|
||||||
|
s.lock.Lock()
|
||||||
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
|
s.data = make(map[interface{}]interface{})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NodbProvider represents a ledis session provider implementation.
|
||||||
|
type NodbProvider struct {
|
||||||
|
c *nodb.DB
|
||||||
|
expire int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init initializes nodb session provider.
|
||||||
|
func (p *NodbProvider) Init(expire int64, configs string) error {
|
||||||
|
p.expire = expire
|
||||||
|
|
||||||
|
cfg := new(config.Config)
|
||||||
|
cfg.DataDir = configs
|
||||||
|
dbs, err := nodb.Open(cfg)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("session/nodb: error opening db: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
p.c, err = dbs.Select(0)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read returns raw session store by session ID.
|
||||||
|
func (p *NodbProvider) Read(sid string) (session.RawStore, error) {
|
||||||
|
if !p.Exist(sid) {
|
||||||
|
if err := p.c.Set([]byte(sid), []byte("")); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var kv map[interface{}]interface{}
|
||||||
|
kvs, err := p.c.Get([]byte(sid))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(kvs) == 0 {
|
||||||
|
kv = make(map[interface{}]interface{})
|
||||||
|
} else {
|
||||||
|
kv, err = session.DecodeGob(kvs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewNodbStore(p.c, sid, p.expire, kv), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exist returns true if session with given ID exists.
|
||||||
|
func (p *NodbProvider) Exist(sid string) bool {
|
||||||
|
count, err := p.c.Exists([]byte(sid))
|
||||||
|
return err == nil && count > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destory deletes a session by session ID.
|
||||||
|
func (p *NodbProvider) Destory(sid string) error {
|
||||||
|
_, err := p.c.Del([]byte(sid))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Regenerate regenerates a session store from old session ID to new one.
|
||||||
|
func (p *NodbProvider) Regenerate(oldsid, sid string) (_ session.RawStore, err error) {
|
||||||
|
if p.Exist(sid) {
|
||||||
|
return nil, fmt.Errorf("new sid '%s' already exists", sid)
|
||||||
|
}
|
||||||
|
|
||||||
|
kvs := make([]byte, 0)
|
||||||
|
if p.Exist(oldsid) {
|
||||||
|
if kvs, err = p.c.Get([]byte(oldsid)); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else if _, err = p.c.Del([]byte(oldsid)); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = p.c.Set([]byte(sid), kvs); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else if _, err = p.c.Expire([]byte(sid), p.expire); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var kv map[interface{}]interface{}
|
||||||
|
if len(kvs) == 0 {
|
||||||
|
kv = make(map[interface{}]interface{})
|
||||||
|
} else {
|
||||||
|
kv, err = session.DecodeGob([]byte(kvs))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewNodbStore(p.c, sid, p.expire, kv), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count counts and returns number of sessions.
|
||||||
|
func (p *NodbProvider) Count() int {
|
||||||
|
// FIXME: how come this library does not have DbSize() method?
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
// GC calls GC to clean expired sessions.
|
||||||
|
func (p *NodbProvider) GC() {}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
session.Register("nodb", &NodbProvider{})
|
||||||
|
}
|
1
Godeps/_workspace/src/github.com/macaron-contrib/session/nodb/nodb.goconvey
generated
vendored
Normal file
1
Godeps/_workspace/src/github.com/macaron-contrib/session/nodb/nodb.goconvey
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
ignore
|
105
Godeps/_workspace/src/github.com/macaron-contrib/session/nodb/nodb_test.go
generated
vendored
Normal file
105
Godeps/_workspace/src/github.com/macaron-contrib/session/nodb/nodb_test.go
generated
vendored
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
// Copyright 2015 Unknwon
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||||
|
// not use this file except in compliance with the License. You may obtain
|
||||||
|
// a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
// License for the specific language governing permissions and limitations
|
||||||
|
// under the License.
|
||||||
|
|
||||||
|
package session
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/Unknwon/macaron"
|
||||||
|
. "github.com/smartystreets/goconvey/convey"
|
||||||
|
|
||||||
|
"github.com/macaron-contrib/session"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_LedisProvider(t *testing.T) {
|
||||||
|
Convey("Test nodb session provider", t, func() {
|
||||||
|
opt := session.Options{
|
||||||
|
Provider: "nodb",
|
||||||
|
ProviderConfig: "./tmp.db",
|
||||||
|
}
|
||||||
|
|
||||||
|
Convey("Basic operation", func() {
|
||||||
|
m := macaron.New()
|
||||||
|
m.Use(session.Sessioner(opt))
|
||||||
|
|
||||||
|
m.Get("/", func(ctx *macaron.Context, sess session.Store) {
|
||||||
|
sess.Set("uname", "unknwon")
|
||||||
|
})
|
||||||
|
m.Get("/reg", func(ctx *macaron.Context, sess session.Store) {
|
||||||
|
raw, err := sess.RegenerateId(ctx)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(raw, ShouldNotBeNil)
|
||||||
|
|
||||||
|
uname := raw.Get("uname")
|
||||||
|
So(uname, ShouldNotBeNil)
|
||||||
|
So(uname, ShouldEqual, "unknwon")
|
||||||
|
})
|
||||||
|
m.Get("/get", func(ctx *macaron.Context, sess session.Store) {
|
||||||
|
sid := sess.ID()
|
||||||
|
So(sid, ShouldNotBeEmpty)
|
||||||
|
|
||||||
|
raw, err := sess.Read(sid)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(raw, ShouldNotBeNil)
|
||||||
|
|
||||||
|
uname := sess.Get("uname")
|
||||||
|
So(uname, ShouldNotBeNil)
|
||||||
|
So(uname, ShouldEqual, "unknwon")
|
||||||
|
|
||||||
|
So(sess.Delete("uname"), ShouldBeNil)
|
||||||
|
So(sess.Get("uname"), ShouldBeNil)
|
||||||
|
|
||||||
|
So(sess.Destory(ctx), ShouldBeNil)
|
||||||
|
})
|
||||||
|
|
||||||
|
resp := httptest.NewRecorder()
|
||||||
|
req, err := http.NewRequest("GET", "/", nil)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
m.ServeHTTP(resp, req)
|
||||||
|
|
||||||
|
cookie := resp.Header().Get("Set-Cookie")
|
||||||
|
|
||||||
|
resp = httptest.NewRecorder()
|
||||||
|
req, err = http.NewRequest("GET", "/reg", nil)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
req.Header.Set("Cookie", cookie)
|
||||||
|
m.ServeHTTP(resp, req)
|
||||||
|
|
||||||
|
cookie = resp.Header().Get("Set-Cookie")
|
||||||
|
|
||||||
|
resp = httptest.NewRecorder()
|
||||||
|
req, err = http.NewRequest("GET", "/get", nil)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
req.Header.Set("Cookie", cookie)
|
||||||
|
m.ServeHTTP(resp, req)
|
||||||
|
|
||||||
|
Convey("Regenrate empty session", func() {
|
||||||
|
m.Get("/empty", func(ctx *macaron.Context, sess session.Store) {
|
||||||
|
raw, err := sess.RegenerateId(ctx)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(raw, ShouldNotBeNil)
|
||||||
|
})
|
||||||
|
|
||||||
|
resp = httptest.NewRecorder()
|
||||||
|
req, err = http.NewRequest("GET", "/empty", nil)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
req.Header.Set("Cookie", "MacaronSession=ad2c7e3cbecfcf486; Path=/;")
|
||||||
|
m.ServeHTTP(resp, req)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
196
Godeps/_workspace/src/github.com/macaron-contrib/session/postgres/postgres.go
generated
vendored
Normal file
196
Godeps/_workspace/src/github.com/macaron-contrib/session/postgres/postgres.go
generated
vendored
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
// Copyright 2013 Beego Authors
|
||||||
|
// Copyright 2014 Unknwon
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||||
|
// not use this file except in compliance with the License. You may obtain
|
||||||
|
// a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
// License for the specific language governing permissions and limitations
|
||||||
|
// under the License.
|
||||||
|
|
||||||
|
package session
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
_ "github.com/lib/pq"
|
||||||
|
|
||||||
|
"github.com/macaron-contrib/session"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PostgresStore represents a postgres session store implementation.
|
||||||
|
type PostgresStore struct {
|
||||||
|
c *sql.DB
|
||||||
|
sid string
|
||||||
|
lock sync.RWMutex
|
||||||
|
data map[interface{}]interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPostgresStore creates and returns a postgres session store.
|
||||||
|
func NewPostgresStore(c *sql.DB, sid string, kv map[interface{}]interface{}) *PostgresStore {
|
||||||
|
return &PostgresStore{
|
||||||
|
c: c,
|
||||||
|
sid: sid,
|
||||||
|
data: kv,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set sets value to given key in session.
|
||||||
|
func (s *PostgresStore) Set(key, value interface{}) error {
|
||||||
|
s.lock.Lock()
|
||||||
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
|
s.data[key] = value
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get gets value by given key in session.
|
||||||
|
func (s *PostgresStore) Get(key interface{}) interface{} {
|
||||||
|
s.lock.RLock()
|
||||||
|
defer s.lock.RUnlock()
|
||||||
|
|
||||||
|
return s.data[key]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete delete a key from session.
|
||||||
|
func (s *PostgresStore) Delete(key interface{}) error {
|
||||||
|
s.lock.Lock()
|
||||||
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
|
delete(s.data, key)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ID returns current session ID.
|
||||||
|
func (s *PostgresStore) ID() string {
|
||||||
|
return s.sid
|
||||||
|
}
|
||||||
|
|
||||||
|
// save postgres session values to database.
|
||||||
|
// must call this method to save values to database.
|
||||||
|
func (s *PostgresStore) Release() error {
|
||||||
|
data, err := session.EncodeGob(s.data)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = s.c.Exec("UPDATE session SET data=$1, expiry=$2 WHERE key=$3",
|
||||||
|
data, time.Now().Unix(), s.sid)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flush deletes all session data.
|
||||||
|
func (s *PostgresStore) Flush() error {
|
||||||
|
s.lock.Lock()
|
||||||
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
|
s.data = make(map[interface{}]interface{})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PostgresProvider represents a postgres session provider implementation.
|
||||||
|
type PostgresProvider struct {
|
||||||
|
c *sql.DB
|
||||||
|
maxlifetime int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init initializes postgres session provider.
|
||||||
|
// connStr: user=a password=b host=localhost port=5432 dbname=c sslmode=disable
|
||||||
|
func (p *PostgresProvider) Init(maxlifetime int64, connStr string) (err error) {
|
||||||
|
p.maxlifetime = maxlifetime
|
||||||
|
|
||||||
|
p.c, err = sql.Open("postgres", connStr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return p.c.Ping()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read returns raw session store by session ID.
|
||||||
|
func (p *PostgresProvider) Read(sid string) (session.RawStore, error) {
|
||||||
|
var data []byte
|
||||||
|
err := p.c.QueryRow("SELECT data FROM session WHERE key=$1", sid).Scan(&data)
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
_, err = p.c.Exec("INSERT INTO session(key,data,expiry) VALUES($1,$2,$3)",
|
||||||
|
sid, "", time.Now().Unix())
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var kv map[interface{}]interface{}
|
||||||
|
if len(data) == 0 {
|
||||||
|
kv = make(map[interface{}]interface{})
|
||||||
|
} else {
|
||||||
|
kv, err = session.DecodeGob(data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewPostgresStore(p.c, sid, kv), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exist returns true if session with given ID exists.
|
||||||
|
func (p *PostgresProvider) Exist(sid string) bool {
|
||||||
|
var data []byte
|
||||||
|
err := p.c.QueryRow("SELECT data FROM session WHERE key=$1", sid).Scan(&data)
|
||||||
|
if err != nil && err != sql.ErrNoRows {
|
||||||
|
panic("session/postgres: error checking existence: " + err.Error())
|
||||||
|
}
|
||||||
|
return err != sql.ErrNoRows
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destory deletes a session by session ID.
|
||||||
|
func (p *PostgresProvider) Destory(sid string) error {
|
||||||
|
_, err := p.c.Exec("DELETE FROM session WHERE key=$1", sid)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Regenerate regenerates a session store from old session ID to new one.
|
||||||
|
func (p *PostgresProvider) Regenerate(oldsid, sid string) (_ session.RawStore, err error) {
|
||||||
|
if p.Exist(sid) {
|
||||||
|
return nil, fmt.Errorf("new sid '%s' already exists", sid)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !p.Exist(oldsid) {
|
||||||
|
if _, err = p.c.Exec("INSERT INTO session(key,data,expiry) VALUES($1,$2,$3)",
|
||||||
|
oldsid, "", time.Now().Unix()); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err = p.c.Exec("UPDATE session SET key=$1 WHERE key=$2", sid, oldsid); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return p.Read(sid)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count counts and returns number of sessions.
|
||||||
|
func (p *PostgresProvider) Count() (total int) {
|
||||||
|
if err := p.c.QueryRow("SELECT COUNT(*) AS NUM FROM session").Scan(&total); err != nil {
|
||||||
|
panic("session/postgres: error counting records: " + err.Error())
|
||||||
|
}
|
||||||
|
return total
|
||||||
|
}
|
||||||
|
|
||||||
|
// GC calls GC to clean expired sessions.
|
||||||
|
func (p *PostgresProvider) GC() {
|
||||||
|
if _, err := p.c.Exec("DELETE FROM session WHERE EXTRACT(EPOCH FROM NOW()) - expiry > $1", p.maxlifetime); err != nil {
|
||||||
|
log.Printf("session/postgres: error garbage collecting: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
session.Register("postgres", &PostgresProvider{})
|
||||||
|
}
|
1
Godeps/_workspace/src/github.com/macaron-contrib/session/postgres/postgres.goconvey
generated
vendored
Normal file
1
Godeps/_workspace/src/github.com/macaron-contrib/session/postgres/postgres.goconvey
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
ignore
|
138
Godeps/_workspace/src/github.com/macaron-contrib/session/postgres/postgres_test.go
generated
vendored
Normal file
138
Godeps/_workspace/src/github.com/macaron-contrib/session/postgres/postgres_test.go
generated
vendored
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
// Copyright 2014 Unknwon
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||||
|
// not use this file except in compliance with the License. You may obtain
|
||||||
|
// a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
// License for the specific language governing permissions and limitations
|
||||||
|
// under the License.
|
||||||
|
|
||||||
|
package session
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/Unknwon/macaron"
|
||||||
|
. "github.com/smartystreets/goconvey/convey"
|
||||||
|
|
||||||
|
"github.com/macaron-contrib/session"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_PostgresProvider(t *testing.T) {
|
||||||
|
Convey("Test postgres session provider", t, func() {
|
||||||
|
opt := session.Options{
|
||||||
|
Provider: "postgres",
|
||||||
|
ProviderConfig: "user=jiahuachen dbname=macaron port=5432 sslmode=disable",
|
||||||
|
}
|
||||||
|
|
||||||
|
Convey("Basic operation", func() {
|
||||||
|
m := macaron.New()
|
||||||
|
m.Use(session.Sessioner(opt))
|
||||||
|
|
||||||
|
m.Get("/", func(ctx *macaron.Context, sess session.Store) {
|
||||||
|
sess.Set("uname", "unknwon")
|
||||||
|
})
|
||||||
|
m.Get("/reg", func(ctx *macaron.Context, sess session.Store) {
|
||||||
|
raw, err := sess.RegenerateId(ctx)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(raw, ShouldNotBeNil)
|
||||||
|
|
||||||
|
uname := raw.Get("uname")
|
||||||
|
So(uname, ShouldNotBeNil)
|
||||||
|
So(uname, ShouldEqual, "unknwon")
|
||||||
|
})
|
||||||
|
m.Get("/get", func(ctx *macaron.Context, sess session.Store) {
|
||||||
|
sid := sess.ID()
|
||||||
|
So(sid, ShouldNotBeEmpty)
|
||||||
|
|
||||||
|
raw, err := sess.Read(sid)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(raw, ShouldNotBeNil)
|
||||||
|
So(raw.Release(), ShouldBeNil)
|
||||||
|
|
||||||
|
uname := sess.Get("uname")
|
||||||
|
So(uname, ShouldNotBeNil)
|
||||||
|
So(uname, ShouldEqual, "unknwon")
|
||||||
|
|
||||||
|
So(sess.Delete("uname"), ShouldBeNil)
|
||||||
|
So(sess.Get("uname"), ShouldBeNil)
|
||||||
|
|
||||||
|
So(sess.Destory(ctx), ShouldBeNil)
|
||||||
|
})
|
||||||
|
|
||||||
|
resp := httptest.NewRecorder()
|
||||||
|
req, err := http.NewRequest("GET", "/", nil)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
m.ServeHTTP(resp, req)
|
||||||
|
|
||||||
|
cookie := resp.Header().Get("Set-Cookie")
|
||||||
|
|
||||||
|
resp = httptest.NewRecorder()
|
||||||
|
req, err = http.NewRequest("GET", "/reg", nil)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
req.Header.Set("Cookie", cookie)
|
||||||
|
m.ServeHTTP(resp, req)
|
||||||
|
|
||||||
|
cookie = resp.Header().Get("Set-Cookie")
|
||||||
|
|
||||||
|
resp = httptest.NewRecorder()
|
||||||
|
req, err = http.NewRequest("GET", "/get", nil)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
req.Header.Set("Cookie", cookie)
|
||||||
|
m.ServeHTTP(resp, req)
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("Regenrate empty session", func() {
|
||||||
|
m := macaron.New()
|
||||||
|
m.Use(session.Sessioner(opt))
|
||||||
|
m.Get("/", func(ctx *macaron.Context, sess session.Store) {
|
||||||
|
raw, err := sess.RegenerateId(ctx)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(raw, ShouldNotBeNil)
|
||||||
|
|
||||||
|
So(sess.Destory(ctx), ShouldBeNil)
|
||||||
|
})
|
||||||
|
|
||||||
|
resp := httptest.NewRecorder()
|
||||||
|
req, err := http.NewRequest("GET", "/", nil)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
req.Header.Set("Cookie", "MacaronSession=ad2c7e3cbecfcf48; Path=/;")
|
||||||
|
m.ServeHTTP(resp, req)
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("GC session", func() {
|
||||||
|
m := macaron.New()
|
||||||
|
opt2 := opt
|
||||||
|
opt2.Gclifetime = 1
|
||||||
|
m.Use(session.Sessioner(opt2))
|
||||||
|
|
||||||
|
m.Get("/", func(sess session.Store) {
|
||||||
|
sess.Set("uname", "unknwon")
|
||||||
|
So(sess.ID(), ShouldNotBeEmpty)
|
||||||
|
uname := sess.Get("uname")
|
||||||
|
So(uname, ShouldNotBeNil)
|
||||||
|
So(uname, ShouldEqual, "unknwon")
|
||||||
|
|
||||||
|
So(sess.Flush(), ShouldBeNil)
|
||||||
|
So(sess.Get("uname"), ShouldBeNil)
|
||||||
|
|
||||||
|
time.Sleep(2 * time.Second)
|
||||||
|
sess.GC()
|
||||||
|
So(sess.Count(), ShouldEqual, 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
resp := httptest.NewRecorder()
|
||||||
|
req, err := http.NewRequest("GET", "/", nil)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
m.ServeHTTP(resp, req)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
211
Godeps/_workspace/src/github.com/macaron-contrib/session/postgres/postgresql.go
generated
vendored
211
Godeps/_workspace/src/github.com/macaron-contrib/session/postgres/postgresql.go
generated
vendored
@ -1,211 +0,0 @@
|
|||||||
// Copyright 2013 Beego Authors
|
|
||||||
// Copyright 2014 Unknwon
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
|
||||||
// not use this file except in compliance with the License. You may obtain
|
|
||||||
// a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
// License for the specific language governing permissions and limitations
|
|
||||||
// under the License.
|
|
||||||
|
|
||||||
package session
|
|
||||||
|
|
||||||
import (
|
|
||||||
"database/sql"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
_ "github.com/lib/pq"
|
|
||||||
|
|
||||||
"github.com/macaron-contrib/session"
|
|
||||||
)
|
|
||||||
|
|
||||||
// PostgresqlSessionStore represents a postgresql session store implementation.
|
|
||||||
type PostgresqlSessionStore struct {
|
|
||||||
c *sql.DB
|
|
||||||
sid string
|
|
||||||
lock sync.RWMutex
|
|
||||||
data map[interface{}]interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set sets value to given key in session.
|
|
||||||
func (s *PostgresqlSessionStore) Set(key, value interface{}) error {
|
|
||||||
s.lock.Lock()
|
|
||||||
defer s.lock.Unlock()
|
|
||||||
|
|
||||||
s.data[key] = value
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get gets value by given key in session.
|
|
||||||
func (s *PostgresqlSessionStore) Get(key interface{}) interface{} {
|
|
||||||
s.lock.RLock()
|
|
||||||
defer s.lock.RUnlock()
|
|
||||||
|
|
||||||
return s.data[key]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete delete a key from session.
|
|
||||||
func (s *PostgresqlSessionStore) Delete(key interface{}) error {
|
|
||||||
s.lock.Lock()
|
|
||||||
defer s.lock.Unlock()
|
|
||||||
|
|
||||||
delete(s.data, key)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ID returns current session ID.
|
|
||||||
func (s *PostgresqlSessionStore) ID() string {
|
|
||||||
return s.sid
|
|
||||||
}
|
|
||||||
|
|
||||||
// save postgresql session values to database.
|
|
||||||
// must call this method to save values to database.
|
|
||||||
func (s *PostgresqlSessionStore) Release() error {
|
|
||||||
defer s.c.Close()
|
|
||||||
|
|
||||||
data, err := session.EncodeGob(s.data)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = s.c.Exec("UPDATE session set session_data=$1, session_expiry=$2 where session_key=$3",
|
|
||||||
data, time.Now().Format(time.RFC3339), s.sid)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flush deletes all session data.
|
|
||||||
func (s *PostgresqlSessionStore) Flush() error {
|
|
||||||
s.lock.Lock()
|
|
||||||
defer s.lock.Unlock()
|
|
||||||
|
|
||||||
s.data = make(map[interface{}]interface{})
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// PostgresqlProvider represents a postgresql session provider implementation.
|
|
||||||
type PostgresqlProvider struct {
|
|
||||||
maxlifetime int64
|
|
||||||
connStr string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *PostgresqlProvider) connectInit() *sql.DB {
|
|
||||||
db, e := sql.Open("postgres", p.connStr)
|
|
||||||
if e != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return db
|
|
||||||
}
|
|
||||||
|
|
||||||
// Init initializes memory session provider.
|
|
||||||
func (p *PostgresqlProvider) Init(maxlifetime int64, connStr string) error {
|
|
||||||
p.maxlifetime = maxlifetime
|
|
||||||
p.connStr = connStr
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read returns raw session store by session ID.
|
|
||||||
func (p *PostgresqlProvider) Read(sid string) (session.RawStore, error) {
|
|
||||||
c := p.connectInit()
|
|
||||||
row := c.QueryRow("select session_data from session where session_key=$1", sid)
|
|
||||||
var sessiondata []byte
|
|
||||||
err := row.Scan(&sessiondata)
|
|
||||||
if err == sql.ErrNoRows {
|
|
||||||
_, err = c.Exec("insert into session(session_key,session_data,session_expiry) values($1,$2,$3)",
|
|
||||||
sid, "", time.Now().Format(time.RFC3339))
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
} else if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var kv map[interface{}]interface{}
|
|
||||||
if len(sessiondata) == 0 {
|
|
||||||
kv = make(map[interface{}]interface{})
|
|
||||||
} else {
|
|
||||||
kv, err = session.DecodeGob(sessiondata)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rs := &PostgresqlSessionStore{c: c, sid: sid, data: kv}
|
|
||||||
return rs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exist returns true if session with given ID exists.
|
|
||||||
func (p *PostgresqlProvider) Exist(sid string) bool {
|
|
||||||
c := p.connectInit()
|
|
||||||
defer c.Close()
|
|
||||||
row := c.QueryRow("select session_data from session where session_key=$1", sid)
|
|
||||||
var sessiondata []byte
|
|
||||||
err := row.Scan(&sessiondata)
|
|
||||||
|
|
||||||
if err == sql.ErrNoRows {
|
|
||||||
return false
|
|
||||||
} else {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Destory deletes a session by session ID.
|
|
||||||
func (p *PostgresqlProvider) Destory(sid string) (err error) {
|
|
||||||
c := p.connectInit()
|
|
||||||
if _, err = c.Exec("DELETE FROM session where session_key=$1", sid); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return c.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Regenerate regenerates a session store from old session ID to new one.
|
|
||||||
func (p *PostgresqlProvider) Regenerate(oldsid, sid string) (session.RawStore, error) {
|
|
||||||
c := p.connectInit()
|
|
||||||
row := c.QueryRow("select session_data from session where session_key=$1", oldsid)
|
|
||||||
var sessiondata []byte
|
|
||||||
err := row.Scan(&sessiondata)
|
|
||||||
if err == sql.ErrNoRows {
|
|
||||||
c.Exec("insert into session(session_key,session_data,session_expiry) values($1,$2,$3)",
|
|
||||||
oldsid, "", time.Now().Format(time.RFC3339))
|
|
||||||
}
|
|
||||||
c.Exec("update session set session_key=$1 where session_key=$2", sid, oldsid)
|
|
||||||
var kv map[interface{}]interface{}
|
|
||||||
if len(sessiondata) == 0 {
|
|
||||||
kv = make(map[interface{}]interface{})
|
|
||||||
} else {
|
|
||||||
kv, err = session.DecodeGob(sessiondata)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rs := &PostgresqlSessionStore{c: c, sid: sid, data: kv}
|
|
||||||
return rs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Count counts and returns number of sessions.
|
|
||||||
func (p *PostgresqlProvider) Count() int {
|
|
||||||
c := p.connectInit()
|
|
||||||
defer c.Close()
|
|
||||||
var total int
|
|
||||||
err := c.QueryRow("SELECT count(*) as num from session").Scan(&total)
|
|
||||||
if err != nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return total
|
|
||||||
}
|
|
||||||
|
|
||||||
// GC calls GC to clean expired sessions.
|
|
||||||
func (mp *PostgresqlProvider) GC() {
|
|
||||||
c := mp.connectInit()
|
|
||||||
c.Exec("DELETE from session where EXTRACT(EPOCH FROM (current_timestamp - session_expiry)) > $1", mp.maxlifetime)
|
|
||||||
c.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
session.Register("postgresql", &PostgresqlProvider{})
|
|
||||||
}
|
|
199
Godeps/_workspace/src/github.com/macaron-contrib/session/redis/redis.go
generated
vendored
199
Godeps/_workspace/src/github.com/macaron-contrib/session/redis/redis.go
generated
vendored
@ -16,31 +16,39 @@
|
|||||||
package session
|
package session
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strconv"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/beego/redigo/redis"
|
"github.com/Unknwon/com"
|
||||||
|
"gopkg.in/ini.v1"
|
||||||
|
"gopkg.in/redis.v2"
|
||||||
|
|
||||||
"github.com/macaron-contrib/session"
|
"github.com/macaron-contrib/session"
|
||||||
)
|
)
|
||||||
|
|
||||||
// redis max pool size
|
// RedisStore represents a redis session store implementation.
|
||||||
var MAX_POOL_SIZE = 100
|
type RedisStore struct {
|
||||||
|
c *redis.Client
|
||||||
|
sid string
|
||||||
|
duration time.Duration
|
||||||
|
lock sync.RWMutex
|
||||||
|
data map[interface{}]interface{}
|
||||||
|
}
|
||||||
|
|
||||||
var redisPool chan redis.Conn
|
// NewRedisStore creates and returns a redis session store.
|
||||||
|
func NewRedisStore(c *redis.Client, sid string, dur time.Duration, kv map[interface{}]interface{}) *RedisStore {
|
||||||
// RedisSessionStore represents a redis session store implementation.
|
return &RedisStore{
|
||||||
type RedisSessionStore struct {
|
c: c,
|
||||||
p *redis.Pool
|
sid: sid,
|
||||||
sid string
|
duration: dur,
|
||||||
lock sync.RWMutex
|
data: kv,
|
||||||
data map[interface{}]interface{}
|
}
|
||||||
maxlifetime int64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set sets value to given key in session.
|
// Set sets value to given key in session.
|
||||||
func (s *RedisSessionStore) Set(key, val interface{}) error {
|
func (s *RedisStore) Set(key, val interface{}) error {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
defer s.lock.Unlock()
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
@ -49,7 +57,7 @@ func (s *RedisSessionStore) Set(key, val interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get gets value by given key in session.
|
// Get gets value by given key in session.
|
||||||
func (s *RedisSessionStore) Get(key interface{}) interface{} {
|
func (s *RedisStore) Get(key interface{}) interface{} {
|
||||||
s.lock.RLock()
|
s.lock.RLock()
|
||||||
defer s.lock.RUnlock()
|
defer s.lock.RUnlock()
|
||||||
|
|
||||||
@ -57,7 +65,7 @@ func (s *RedisSessionStore) Get(key interface{}) interface{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Delete delete a key from session.
|
// Delete delete a key from session.
|
||||||
func (s *RedisSessionStore) Delete(key interface{}) error {
|
func (s *RedisStore) Delete(key interface{}) error {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
defer s.lock.Unlock()
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
@ -66,26 +74,22 @@ func (s *RedisSessionStore) Delete(key interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ID returns current session ID.
|
// ID returns current session ID.
|
||||||
func (s *RedisSessionStore) ID() string {
|
func (s *RedisStore) ID() string {
|
||||||
return s.sid
|
return s.sid
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release releases resource and save data to provider.
|
// Release releases resource and save data to provider.
|
||||||
func (s *RedisSessionStore) Release() error {
|
func (s *RedisStore) Release() error {
|
||||||
c := s.p.Get()
|
|
||||||
defer c.Close()
|
|
||||||
|
|
||||||
data, err := session.EncodeGob(s.data)
|
data, err := session.EncodeGob(s.data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = c.Do("SETEX", s.sid, s.maxlifetime, string(data))
|
return s.c.SetEx(s.sid, s.duration, string(data)).Err()
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flush deletes all session data.
|
// Flush deletes all session data.
|
||||||
func (s *RedisSessionStore) Flush() error {
|
func (s *RedisStore) Flush() error {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
defer s.lock.Unlock()
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
@ -95,59 +99,65 @@ func (s *RedisSessionStore) Flush() error {
|
|||||||
|
|
||||||
// RedisProvider represents a redis session provider implementation.
|
// RedisProvider represents a redis session provider implementation.
|
||||||
type RedisProvider struct {
|
type RedisProvider struct {
|
||||||
maxlifetime int64
|
c *redis.Client
|
||||||
connAddr string
|
duration time.Duration
|
||||||
poolsize int
|
|
||||||
password string
|
|
||||||
poollist *redis.Pool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init initializes memory session provider.
|
// Init initializes redis session provider.
|
||||||
// connStr: <redis server addr>,<pool size>,<password>
|
// configs: network=tcp,addr=:6379,password=macaron,db=0,pool_size=100,idle_timeout=180
|
||||||
// e.g. 127.0.0.1:6379,100,macaron
|
func (p *RedisProvider) Init(maxlifetime int64, configs string) (err error) {
|
||||||
func (p *RedisProvider) Init(maxlifetime int64, connStr string) error {
|
p.duration, err = time.ParseDuration(fmt.Sprintf("%ds", maxlifetime))
|
||||||
p.maxlifetime = maxlifetime
|
if err != nil {
|
||||||
configs := strings.Split(connStr, ",")
|
return err
|
||||||
if len(configs) > 0 {
|
|
||||||
p.connAddr = configs[0]
|
|
||||||
}
|
}
|
||||||
if len(configs) > 1 {
|
|
||||||
poolsize, err := strconv.Atoi(configs[1])
|
|
||||||
if err != nil || poolsize <= 0 {
|
|
||||||
p.poolsize = MAX_POOL_SIZE
|
|
||||||
} else {
|
|
||||||
p.poolsize = poolsize
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
p.poolsize = MAX_POOL_SIZE
|
|
||||||
}
|
|
||||||
if len(configs) > 2 {
|
|
||||||
p.password = configs[2]
|
|
||||||
}
|
|
||||||
p.poollist = redis.NewPool(func() (redis.Conn, error) {
|
|
||||||
c, err := redis.Dial("tcp", p.connAddr)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if p.password != "" {
|
|
||||||
if _, err := c.Do("AUTH", p.password); err != nil {
|
|
||||||
c.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return c, err
|
|
||||||
}, p.poolsize)
|
|
||||||
|
|
||||||
return p.poollist.Get().Err()
|
cfg, err := ini.Load([]byte(strings.Replace(configs, ",", "\n", -1)))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
opt := &redis.Options{
|
||||||
|
Network: "tcp",
|
||||||
|
}
|
||||||
|
for k, v := range cfg.Section("").KeysHash() {
|
||||||
|
switch k {
|
||||||
|
case "network":
|
||||||
|
opt.Network = v
|
||||||
|
case "addr":
|
||||||
|
opt.Addr = v
|
||||||
|
case "password":
|
||||||
|
opt.Password = v
|
||||||
|
case "db":
|
||||||
|
opt.DB = com.StrTo(v).MustInt64()
|
||||||
|
case "pool_size":
|
||||||
|
opt.PoolSize = com.StrTo(v).MustInt()
|
||||||
|
case "idle_timeout":
|
||||||
|
opt.IdleTimeout, err = time.ParseDuration(v + "s")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error parsing idle timeout: %v", err)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("session/redis: unsupported option '%s'", k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p.c = redis.NewClient(opt)
|
||||||
|
return p.c.Ping().Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read returns raw session store by session ID.
|
// Read returns raw session store by session ID.
|
||||||
func (p *RedisProvider) Read(sid string) (session.RawStore, error) {
|
func (p *RedisProvider) Read(sid string) (session.RawStore, error) {
|
||||||
c := p.poollist.Get()
|
if !p.Exist(sid) {
|
||||||
defer c.Close()
|
if err := p.c.Set(sid, "").Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
kvs, err := redis.String(c.Do("GET", sid))
|
|
||||||
var kv map[interface{}]interface{}
|
var kv map[interface{}]interface{}
|
||||||
|
kvs, err := p.c.Get(sid).Result()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
if len(kvs) == 0 {
|
if len(kvs) == 0 {
|
||||||
kv = make(map[interface{}]interface{})
|
kv = make(map[interface{}]interface{})
|
||||||
} else {
|
} else {
|
||||||
@ -157,48 +167,41 @@ func (p *RedisProvider) Read(sid string) (session.RawStore, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rs := &RedisSessionStore{p: p.poollist, sid: sid, data: kv, maxlifetime: p.maxlifetime}
|
return NewRedisStore(p.c, sid, p.duration, kv), nil
|
||||||
return rs, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exist returns true if session with given ID exists.
|
// Exist returns true if session with given ID exists.
|
||||||
func (p *RedisProvider) Exist(sid string) bool {
|
func (p *RedisProvider) Exist(sid string) bool {
|
||||||
c := p.poollist.Get()
|
has, err := p.c.Exists(sid).Result()
|
||||||
defer c.Close()
|
return err == nil && has
|
||||||
|
|
||||||
if existed, err := redis.Int(c.Do("EXISTS", sid)); err != nil || existed == 0 {
|
|
||||||
return false
|
|
||||||
} else {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destory deletes a session by session ID.
|
// Destory deletes a session by session ID.
|
||||||
func (p *RedisProvider) Destory(sid string) error {
|
func (p *RedisProvider) Destory(sid string) error {
|
||||||
c := p.poollist.Get()
|
return p.c.Del(sid).Err()
|
||||||
defer c.Close()
|
|
||||||
|
|
||||||
_, err := c.Do("DEL", sid)
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Regenerate regenerates a session store from old session ID to new one.
|
// Regenerate regenerates a session store from old session ID to new one.
|
||||||
func (p *RedisProvider) Regenerate(oldsid, sid string) (session.RawStore, error) {
|
func (p *RedisProvider) Regenerate(oldsid, sid string) (_ session.RawStore, err error) {
|
||||||
c := p.poollist.Get()
|
if p.Exist(sid) {
|
||||||
defer c.Close()
|
return nil, fmt.Errorf("new sid '%s' already exists", sid)
|
||||||
|
} else if !p.Exist(oldsid) {
|
||||||
if existed, _ := redis.Int(c.Do("EXISTS", oldsid)); existed == 0 {
|
// Make a fake old session.
|
||||||
// oldsid doesn't exists, set the new sid directly
|
if err = p.c.SetEx(oldsid, p.duration, "").Err(); err != nil {
|
||||||
// ignore error here, since if it return error
|
return nil, err
|
||||||
// the existed value will be 0
|
}
|
||||||
c.Do("SET", sid, "", "EX", p.maxlifetime)
|
}
|
||||||
} else {
|
|
||||||
c.Do("RENAME", oldsid, sid)
|
if err = p.c.Rename(oldsid, sid).Err(); err != nil {
|
||||||
c.Do("EXPIRE", sid, p.maxlifetime)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
kvs, err := redis.String(c.Do("GET", sid))
|
|
||||||
var kv map[interface{}]interface{}
|
var kv map[interface{}]interface{}
|
||||||
|
kvs, err := p.c.Get(sid).Result()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
if len(kvs) == 0 {
|
if len(kvs) == 0 {
|
||||||
kv = make(map[interface{}]interface{})
|
kv = make(map[interface{}]interface{})
|
||||||
} else {
|
} else {
|
||||||
@ -208,14 +211,12 @@ func (p *RedisProvider) Regenerate(oldsid, sid string) (session.RawStore, error)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rs := &RedisSessionStore{p: p.poollist, sid: sid, data: kv, maxlifetime: p.maxlifetime}
|
return NewRedisStore(p.c, sid, p.duration, kv), nil
|
||||||
return rs, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count counts and returns number of sessions.
|
// Count counts and returns number of sessions.
|
||||||
func (p *RedisProvider) Count() int {
|
func (p *RedisProvider) Count() int {
|
||||||
// FIXME
|
return int(p.c.DbSize().Val())
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GC calls GC to clean expired sessions.
|
// GC calls GC to clean expired sessions.
|
||||||
|
1
Godeps/_workspace/src/github.com/macaron-contrib/session/redis/redis.goconvey
generated
vendored
Normal file
1
Godeps/_workspace/src/github.com/macaron-contrib/session/redis/redis.goconvey
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
ignore
|
107
Godeps/_workspace/src/github.com/macaron-contrib/session/redis/redis_test.go
generated
vendored
Normal file
107
Godeps/_workspace/src/github.com/macaron-contrib/session/redis/redis_test.go
generated
vendored
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
// Copyright 2014 Unknwon
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||||
|
// not use this file except in compliance with the License. You may obtain
|
||||||
|
// a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
// License for the specific language governing permissions and limitations
|
||||||
|
// under the License.
|
||||||
|
|
||||||
|
package session
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/Unknwon/macaron"
|
||||||
|
. "github.com/smartystreets/goconvey/convey"
|
||||||
|
|
||||||
|
"github.com/macaron-contrib/session"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_RedisProvider(t *testing.T) {
|
||||||
|
Convey("Test redis session provider", t, func() {
|
||||||
|
opt := session.Options{
|
||||||
|
Provider: "redis",
|
||||||
|
ProviderConfig: "addr=:6379",
|
||||||
|
}
|
||||||
|
|
||||||
|
Convey("Basic operation", func() {
|
||||||
|
m := macaron.New()
|
||||||
|
m.Use(session.Sessioner(opt))
|
||||||
|
|
||||||
|
m.Get("/", func(ctx *macaron.Context, sess session.Store) {
|
||||||
|
sess.Set("uname", "unknwon")
|
||||||
|
})
|
||||||
|
m.Get("/reg", func(ctx *macaron.Context, sess session.Store) {
|
||||||
|
raw, err := sess.RegenerateId(ctx)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(raw, ShouldNotBeNil)
|
||||||
|
|
||||||
|
uname := raw.Get("uname")
|
||||||
|
So(uname, ShouldNotBeNil)
|
||||||
|
So(uname, ShouldEqual, "unknwon")
|
||||||
|
})
|
||||||
|
m.Get("/get", func(ctx *macaron.Context, sess session.Store) {
|
||||||
|
sid := sess.ID()
|
||||||
|
So(sid, ShouldNotBeEmpty)
|
||||||
|
|
||||||
|
raw, err := sess.Read(sid)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(raw, ShouldNotBeNil)
|
||||||
|
|
||||||
|
uname := sess.Get("uname")
|
||||||
|
So(uname, ShouldNotBeNil)
|
||||||
|
So(uname, ShouldEqual, "unknwon")
|
||||||
|
|
||||||
|
So(sess.Delete("uname"), ShouldBeNil)
|
||||||
|
So(sess.Get("uname"), ShouldBeNil)
|
||||||
|
|
||||||
|
So(sess.Destory(ctx), ShouldBeNil)
|
||||||
|
})
|
||||||
|
|
||||||
|
resp := httptest.NewRecorder()
|
||||||
|
req, err := http.NewRequest("GET", "/", nil)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
m.ServeHTTP(resp, req)
|
||||||
|
|
||||||
|
cookie := resp.Header().Get("Set-Cookie")
|
||||||
|
|
||||||
|
resp = httptest.NewRecorder()
|
||||||
|
req, err = http.NewRequest("GET", "/reg", nil)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
req.Header.Set("Cookie", cookie)
|
||||||
|
m.ServeHTTP(resp, req)
|
||||||
|
|
||||||
|
cookie = resp.Header().Get("Set-Cookie")
|
||||||
|
|
||||||
|
resp = httptest.NewRecorder()
|
||||||
|
req, err = http.NewRequest("GET", "/get", nil)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
req.Header.Set("Cookie", cookie)
|
||||||
|
m.ServeHTTP(resp, req)
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("Regenrate empty session", func() {
|
||||||
|
m := macaron.New()
|
||||||
|
m.Use(session.Sessioner(opt))
|
||||||
|
m.Get("/", func(ctx *macaron.Context, sess session.Store) {
|
||||||
|
raw, err := sess.RegenerateId(ctx)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(raw, ShouldNotBeNil)
|
||||||
|
})
|
||||||
|
|
||||||
|
resp := httptest.NewRecorder()
|
||||||
|
req, err := http.NewRequest("GET", "/", nil)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
req.Header.Set("Cookie", "MacaronSession=ad2c7e3cbecfcf486; Path=/;")
|
||||||
|
m.ServeHTTP(resp, req)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
44
Godeps/_workspace/src/github.com/macaron-contrib/session/session.go
generated
vendored
44
Godeps/_workspace/src/github.com/macaron-contrib/session/session.go
generated
vendored
@ -13,7 +13,7 @@
|
|||||||
// License for the specific language governing permissions and limitations
|
// License for the specific language governing permissions and limitations
|
||||||
// under the License.
|
// under the License.
|
||||||
|
|
||||||
// Package session a middleware that provides the session manager of Macaron.
|
// Package session a middleware that provides the session management of Macaron.
|
||||||
package session
|
package session
|
||||||
|
|
||||||
// NOTE: last sync 000033e on Nov 4, 2014.
|
// NOTE: last sync 000033e on Nov 4, 2014.
|
||||||
@ -28,7 +28,7 @@ import (
|
|||||||
"github.com/Unknwon/macaron"
|
"github.com/Unknwon/macaron"
|
||||||
)
|
)
|
||||||
|
|
||||||
const _VERSION = "0.1.1"
|
const _VERSION = "0.1.6"
|
||||||
|
|
||||||
func Version() string {
|
func Version() string {
|
||||||
return _VERSION
|
return _VERSION
|
||||||
@ -37,11 +37,11 @@ func Version() string {
|
|||||||
// RawStore is the interface that operates the session data.
|
// RawStore is the interface that operates the session data.
|
||||||
type RawStore interface {
|
type RawStore interface {
|
||||||
// Set sets value to given key in session.
|
// Set sets value to given key in session.
|
||||||
Set(key, value interface{}) error
|
Set(interface{}, interface{}) error
|
||||||
// Get gets value by given key in session.
|
// Get gets value by given key in session.
|
||||||
Get(key interface{}) interface{}
|
Get(interface{}) interface{}
|
||||||
// Delete delete a key from session.
|
// Delete deletes a key from session.
|
||||||
Delete(key interface{}) error
|
Delete(interface{}) error
|
||||||
// ID returns current session ID.
|
// ID returns current session ID.
|
||||||
ID() string
|
ID() string
|
||||||
// Release releases session resource and save data to provider.
|
// Release releases session resource and save data to provider.
|
||||||
@ -54,7 +54,7 @@ type RawStore interface {
|
|||||||
type Store interface {
|
type Store interface {
|
||||||
RawStore
|
RawStore
|
||||||
// Read returns raw session store by session ID.
|
// Read returns raw session store by session ID.
|
||||||
Read(sid string) (RawStore, error)
|
Read(string) (RawStore, error)
|
||||||
// Destory deletes a session.
|
// Destory deletes a session.
|
||||||
Destory(*macaron.Context) error
|
Destory(*macaron.Context) error
|
||||||
// RegenerateId regenerates a session store from old session ID to new one.
|
// RegenerateId regenerates a session store from old session ID to new one.
|
||||||
@ -111,7 +111,7 @@ func prepareOptions(options []Options) Options {
|
|||||||
if len(opt.Provider) == 0 {
|
if len(opt.Provider) == 0 {
|
||||||
opt.Provider = sec.Key("PROVIDER").MustString("memory")
|
opt.Provider = sec.Key("PROVIDER").MustString("memory")
|
||||||
}
|
}
|
||||||
if len(opt.ProviderConfig) == 0 && opt.Provider == "file" {
|
if len(opt.ProviderConfig) == 0 {
|
||||||
opt.ProviderConfig = sec.Key("PROVIDER_CONFIG").MustString("data/sessions")
|
opt.ProviderConfig = sec.Key("PROVIDER_CONFIG").MustString("data/sessions")
|
||||||
}
|
}
|
||||||
if len(opt.CookieName) == 0 {
|
if len(opt.CookieName) == 0 {
|
||||||
@ -155,7 +155,7 @@ func Sessioner(options ...Options) macaron.Handler {
|
|||||||
return func(ctx *macaron.Context) {
|
return func(ctx *macaron.Context) {
|
||||||
sess, err := manager.Start(ctx)
|
sess, err := manager.Start(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("session: " + err.Error())
|
panic("session(start): " + err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get flash.
|
// Get flash.
|
||||||
@ -187,8 +187,8 @@ func Sessioner(options ...Options) macaron.Handler {
|
|||||||
|
|
||||||
ctx.Next()
|
ctx.Next()
|
||||||
|
|
||||||
if sess.Release() != nil {
|
if err = sess.Release(); err != nil {
|
||||||
panic("session: " + err.Error())
|
panic("session(release): " + err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -242,17 +242,14 @@ type Manager struct {
|
|||||||
func NewManager(name string, opt Options) (*Manager, error) {
|
func NewManager(name string, opt Options) (*Manager, error) {
|
||||||
p, ok := providers[name]
|
p, ok := providers[name]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("session: unknown provider ‘%q’(forgotten import?)", name)
|
return nil, fmt.Errorf("session: unknown provider '%s'(forgotten import?)", name)
|
||||||
}
|
}
|
||||||
if err := p.Init(opt.Maxlifetime, opt.ProviderConfig); err != nil {
|
return &Manager{p, opt}, p.Init(opt.Maxlifetime, opt.ProviderConfig)
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &Manager{p, opt}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// sessionId generates a new session ID with rand string, unix nano time, remote addr by hash function.
|
// sessionId generates a new session ID with rand string, unix nano time, remote addr by hash function.
|
||||||
func (m *Manager) sessionId() string {
|
func (m *Manager) sessionId() string {
|
||||||
return hex.EncodeToString(generateRandomKey(m.opt.IDLength))
|
return hex.EncodeToString(generateRandomKey(m.opt.IDLength / 2))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start starts a session by generating new one
|
// Start starts a session by generating new one
|
||||||
@ -315,16 +312,9 @@ func (m *Manager) Destory(ctx *macaron.Context) error {
|
|||||||
func (m *Manager) RegenerateId(ctx *macaron.Context) (sess RawStore, err error) {
|
func (m *Manager) RegenerateId(ctx *macaron.Context) (sess RawStore, err error) {
|
||||||
sid := m.sessionId()
|
sid := m.sessionId()
|
||||||
oldsid := ctx.GetCookie(m.opt.CookieName)
|
oldsid := ctx.GetCookie(m.opt.CookieName)
|
||||||
if len(oldsid) == 0 {
|
sess, err = m.provider.Regenerate(oldsid, sid)
|
||||||
sess, err = m.provider.Read(oldsid)
|
if err != nil {
|
||||||
if err != nil {
|
return nil, err
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
sess, err = m.provider.Regenerate(oldsid, sid)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ck := &http.Cookie{
|
ck := &http.Cookie{
|
||||||
Name: m.opt.CookieName,
|
Name: m.opt.CookieName,
|
||||||
|
2
Godeps/_workspace/src/github.com/macaron-contrib/session/session_test.go
generated
vendored
2
Godeps/_workspace/src/github.com/macaron-contrib/session/session_test.go
generated
vendored
@ -42,7 +42,7 @@ func Test_Sessioner(t *testing.T) {
|
|||||||
m.ServeHTTP(resp, req)
|
m.ServeHTTP(resp, req)
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("Register invalid provider that", t, func() {
|
Convey("Register invalid provider", t, func() {
|
||||||
Convey("Provider not exists", func() {
|
Convey("Provider not exists", func() {
|
||||||
defer func() {
|
defer func() {
|
||||||
So(recover(), ShouldNotBeNil)
|
So(recover(), ShouldNotBeNil)
|
||||||
|
30
Godeps/_workspace/src/github.com/macaron-contrib/session/utils.go
generated
vendored
30
Godeps/_workspace/src/github.com/macaron-contrib/session/utils.go
generated
vendored
@ -24,39 +24,19 @@ import (
|
|||||||
"github.com/Unknwon/com"
|
"github.com/Unknwon/com"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
|
||||||
gob.Register([]interface{}{})
|
|
||||||
gob.Register(map[int]interface{}{})
|
|
||||||
gob.Register(map[string]interface{}{})
|
|
||||||
gob.Register(map[interface{}]interface{}{})
|
|
||||||
gob.Register(map[string]string{})
|
|
||||||
gob.Register(map[int]string{})
|
|
||||||
gob.Register(map[int]int{})
|
|
||||||
gob.Register(map[int]int64{})
|
|
||||||
}
|
|
||||||
|
|
||||||
func EncodeGob(obj map[interface{}]interface{}) ([]byte, error) {
|
func EncodeGob(obj map[interface{}]interface{}) ([]byte, error) {
|
||||||
for _, v := range obj {
|
for _, v := range obj {
|
||||||
gob.Register(v)
|
gob.Register(v)
|
||||||
}
|
}
|
||||||
buf := bytes.NewBuffer(nil)
|
buf := bytes.NewBuffer(nil)
|
||||||
enc := gob.NewEncoder(buf)
|
err := gob.NewEncoder(buf).Encode(obj)
|
||||||
err := enc.Encode(obj)
|
return buf.Bytes(), err
|
||||||
if err != nil {
|
|
||||||
return []byte(""), err
|
|
||||||
}
|
|
||||||
return buf.Bytes(), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func DecodeGob(encoded []byte) (map[interface{}]interface{}, error) {
|
func DecodeGob(encoded []byte) (out map[interface{}]interface{}, err error) {
|
||||||
buf := bytes.NewBuffer(encoded)
|
buf := bytes.NewBuffer(encoded)
|
||||||
dec := gob.NewDecoder(buf)
|
err = gob.NewDecoder(buf).Decode(&out)
|
||||||
var out map[interface{}]interface{}
|
return out, err
|
||||||
err := dec.Decode(&out)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return out, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// generateRandomKey creates a random key with the given strength.
|
// generateRandomKey creates a random key with the given strength.
|
||||||
|
Loading…
Reference in New Issue
Block a user