xxxxxxx
This commit is contained in:
parent
b751fc5eb4
commit
61af9f0c8b
5 changed files with 118 additions and 65 deletions
41
session.go
41
session.go
|
@ -32,11 +32,29 @@ func ProviderNames() []string {
|
||||||
return prdnames
|
return prdnames
|
||||||
}
|
}
|
||||||
|
|
||||||
// MilisPerSec return time resolution (milliseconds / 1sec)
|
// MilisPerSec return time resolution (milliseconds / 1sec) changed for short time in testing
|
||||||
func MilisPerSec() int64 {
|
func MilisPerSec() int64 {
|
||||||
return milis
|
return milis
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Provider interace implement lifecycle for one session
|
||||||
|
type Provider interface {
|
||||||
|
//set additional params for provider ex: sql db connection, filesystem path .. etc.
|
||||||
|
SetParams(params any) error
|
||||||
|
//create new session using sid value
|
||||||
|
Init(sid string) (Session, error)
|
||||||
|
//read and return existing session by id or if not exist create new session
|
||||||
|
Read(sid string) (Session, error)
|
||||||
|
//destroy remove session with sid from storage if exist
|
||||||
|
Destroy(sid string) error
|
||||||
|
//regenerate id change old sid to newsid and preserve existing session data
|
||||||
|
ChangeID(oldsid, newsid string) (err error)
|
||||||
|
//Exists return true if session with sid exist
|
||||||
|
Exists(sid string) bool
|
||||||
|
//gc remove all outdated sessions
|
||||||
|
GC(maxlifetime int64)
|
||||||
|
}
|
||||||
|
|
||||||
// Session interface implement storage for one session and have maxLifetime and lastAccessTime
|
// Session interface implement storage for one session and have maxLifetime and lastAccessTime
|
||||||
type Session interface {
|
type Session interface {
|
||||||
//set session value and update last access time
|
//set session value and update last access time
|
||||||
|
@ -49,22 +67,6 @@ type Session interface {
|
||||||
SessionID() string
|
SessionID() string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provider interace implement lifecycle for one session
|
|
||||||
type Provider interface {
|
|
||||||
//create new session using sid value
|
|
||||||
Init(sid string) (Session, error)
|
|
||||||
//Exists return true if session with sid exist
|
|
||||||
Exists(sid string) bool
|
|
||||||
//read return existing session by id or if not exist create new session
|
|
||||||
Read(sid string) (Session, error)
|
|
||||||
//destroy remove session with sid from storage if exist
|
|
||||||
Destroy(sid string) error
|
|
||||||
//regenerate id change old sid to newsid and preserve existing session data
|
|
||||||
RegenerateID(oldsid, newsid string) (err error)
|
|
||||||
//gc remove all sessions with > maxLifetime
|
|
||||||
GC(maxlifetime int64)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register makes a session provide available by the provided name.
|
// Register makes a session provide available by the provided name.
|
||||||
// If Register is called twice with the same name or if driver is nil, it panics.
|
// If Register is called twice with the same name or if driver is nil, it panics.
|
||||||
func Register(name string, provide Provider) {
|
func Register(name string, provide Provider) {
|
||||||
|
@ -91,13 +93,14 @@ type SessOpts struct {
|
||||||
Ssl bool
|
Ssl bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewManager create new *Manager using SesOpts and aditional any other opts
|
// NewManager create new *Manager using SesOpts and aditional any other opts for using in provider
|
||||||
func NewManager(providerName string, sopts *SessOpts, adopts any) (*Manager, error) {
|
func NewManager(providerName string, sopts *SessOpts, adopts any) (*Manager, error) {
|
||||||
var prv Provider
|
var prv Provider
|
||||||
var ok bool
|
var ok bool
|
||||||
if prv, ok = provides[providerName]; !ok {
|
if prv, ok = provides[providerName]; !ok {
|
||||||
return nil, fmt.Errorf("session: Provider: %q not found (forgotten import?)", providerName)
|
return nil, fmt.Errorf("session: Provider: %q not found (forgotten import?)", providerName)
|
||||||
}
|
}
|
||||||
|
prv.SetParams(adopts)
|
||||||
m := &Manager{
|
m := &Manager{
|
||||||
provider: prv,
|
provider: prv,
|
||||||
sessOpts: sopts,
|
sessOpts: sopts,
|
||||||
|
@ -169,7 +172,7 @@ func (manager *Manager) Exists(sid string) bool {
|
||||||
func (manager *Manager) RegenerateID(w http.ResponseWriter, r *http.Request) {
|
func (manager *Manager) RegenerateID(w http.ResponseWriter, r *http.Request) {
|
||||||
if ck, err := r.Cookie(manager.sessOpts.CookieName); err == nil && ck.Value != "" {
|
if ck, err := r.Cookie(manager.sessOpts.CookieName); err == nil && ck.Value != "" {
|
||||||
if newid, err := manager.sessionID(); err != nil {
|
if newid, err := manager.sessionID(); err != nil {
|
||||||
manager.provider.RegenerateID(ck.Value, newid)
|
manager.provider.ChangeID(ck.Value, newid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
// Package file implements sessions saved into filesystem persistently encoded using gob
|
|
||||||
package file
|
|
44
storage/files/files.go
Normal file
44
storage/files/files.go
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
// Package files implements sessions saved into filesystem persistently encoded using gob
|
||||||
|
package files
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
sessDir string = "go-session"
|
||||||
|
sessExt string = "gsd"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProviderFiles implement filesystem session provider
|
||||||
|
type ProviderFiles struct {
|
||||||
|
sessPath string
|
||||||
|
lock sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pder *ProviderFiles) ckdir() string {
|
||||||
|
return pder.sessPath + sessDir
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetParams for files session provider set base path in filesystem for save sessions
|
||||||
|
func (pder *ProviderFiles) SetParams(p any) (err error) {
|
||||||
|
if p != nil {
|
||||||
|
if s, ok := p.(string); ok {
|
||||||
|
pder.sessPath = s
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return fmt.Errorf("Parameter for files session provider is not string")
|
||||||
|
}
|
||||||
|
return fmt.Errorf("Parameter for files session provider must not be nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init create session file if not exists and retturn *Session
|
||||||
|
func (pder *ProviderFiles) Init(sid string) (err error) {
|
||||||
|
//sessdir := sid + sessExt
|
||||||
|
return
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ package memory
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"container/list"
|
"container/list"
|
||||||
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -16,47 +17,6 @@ func init() {
|
||||||
session.Register("memory", pder)
|
session.Register("memory", pder)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SessionMemory implement sessionma.Session interface only in memory
|
|
||||||
type SessionMemory struct {
|
|
||||||
sid string
|
|
||||||
atime time.Time
|
|
||||||
data map[any]any
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sm *SessionMemory) resolvepanic(err *error) {
|
|
||||||
if r := recover(); r != nil {
|
|
||||||
*err = r.(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set -
|
|
||||||
func (sm *SessionMemory) Set(k any, v any) (err error) {
|
|
||||||
defer pder.updateAtime(sm.sid)
|
|
||||||
defer sm.resolvepanic(&err)
|
|
||||||
sm.data[k] = v
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get -
|
|
||||||
func (sm *SessionMemory) Get(k any) (v any, err error) {
|
|
||||||
defer pder.updateAtime(sm.sid)
|
|
||||||
defer sm.resolvepanic(&err)
|
|
||||||
return sm.data[k], err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete -
|
|
||||||
func (sm *SessionMemory) Delete(k any) (err error) {
|
|
||||||
defer pder.updateAtime(sm.sid)
|
|
||||||
|
|
||||||
delete(sm.data, k)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// SessionID -
|
|
||||||
func (sm *SessionMemory) SessionID() string {
|
|
||||||
return sm.sid
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProviderMemory implement memory session provider
|
// ProviderMemory implement memory session provider
|
||||||
type ProviderMemory struct {
|
type ProviderMemory struct {
|
||||||
lock sync.Mutex
|
lock sync.Mutex
|
||||||
|
@ -73,6 +33,11 @@ func (pder *ProviderMemory) updateAtime(sid string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetParams for memory provider not possible
|
||||||
|
func (pder *ProviderMemory) SetParams(pr any) error {
|
||||||
|
return fmt.Errorf("Not possible set parameters for memory session provider")
|
||||||
|
}
|
||||||
|
|
||||||
// Init create new session store for sid
|
// Init create new session store for sid
|
||||||
func (pder *ProviderMemory) Init(sid string) (ses session.Session, err error) {
|
func (pder *ProviderMemory) Init(sid string) (ses session.Session, err error) {
|
||||||
pder.lock.Lock()
|
pder.lock.Lock()
|
||||||
|
@ -114,8 +79,8 @@ func (pder *ProviderMemory) Destroy(sid string) (err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegenerateID replace session ID to new one and preserve all data
|
// ChangeID replace session ID to new one and preserve all data
|
||||||
func (pder *ProviderMemory) RegenerateID(oldsid, newsid string) (err error) {
|
func (pder *ProviderMemory) ChangeID(oldsid, newsid string) (err error) {
|
||||||
pder.lock.Lock()
|
pder.lock.Lock()
|
||||||
defer pder.lock.Unlock()
|
defer pder.lock.Unlock()
|
||||||
if ssel, ok := pder.sessions[oldsid]; ok {
|
if ssel, ok := pder.sessions[oldsid]; ok {
|
||||||
|
@ -145,3 +110,44 @@ func (pder *ProviderMemory) GC(maxlifetime int64) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SessionMemory implement sessionma.Session interface only in memory
|
||||||
|
type SessionMemory struct {
|
||||||
|
sid string
|
||||||
|
atime time.Time
|
||||||
|
data map[any]any
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sm *SessionMemory) resolvepanic(err *error) {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
*err = r.(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set -
|
||||||
|
func (sm *SessionMemory) Set(k any, v any) (err error) {
|
||||||
|
defer pder.updateAtime(sm.sid)
|
||||||
|
defer sm.resolvepanic(&err)
|
||||||
|
sm.data[k] = v
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get -
|
||||||
|
func (sm *SessionMemory) Get(k any) (v any, err error) {
|
||||||
|
defer pder.updateAtime(sm.sid)
|
||||||
|
defer sm.resolvepanic(&err)
|
||||||
|
return sm.data[k], err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete -
|
||||||
|
func (sm *SessionMemory) Delete(k any) (err error) {
|
||||||
|
defer pder.updateAtime(sm.sid)
|
||||||
|
|
||||||
|
delete(sm.data, k)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// SessionID -
|
||||||
|
func (sm *SessionMemory) SessionID() string {
|
||||||
|
return sm.sid
|
||||||
|
}
|
||||||
|
|
|
@ -287,6 +287,7 @@ func TestRunAll(t *testing.T) {
|
||||||
var err error
|
var err error
|
||||||
jar, _ := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List})
|
jar, _ := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List})
|
||||||
testclient.Jar = jar
|
testclient.Jar = jar
|
||||||
|
|
||||||
sessopts := &session.SessOpts{
|
sessopts := &session.SessOpts{
|
||||||
CookieName: sid,
|
CookieName: sid,
|
||||||
MaxLifetime: 180, Ssl: true,
|
MaxLifetime: 180, Ssl: true,
|
||||||
|
@ -295,9 +296,10 @@ func TestRunAll(t *testing.T) {
|
||||||
if sm, err = session.NewManager(pn, sessopts, nil); err != nil {
|
if sm, err = session.NewManager(pn, sessopts, nil); err != nil {
|
||||||
t.Errorf("Session provider %s failed initialize err: %v", pn, err)
|
t.Errorf("Session provider %s failed initialize err: %v", pn, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fns := []func(t *testing.T){t1, t2, t3, t4, t5, t6, t7, t8, t9}
|
fns := []func(t *testing.T){t1, t2, t3, t4, t5, t6, t7, t8, t9}
|
||||||
for idx, fn := range fns {
|
for idx, fn := range fns {
|
||||||
t.Run(fmt.Sprintf("Test%d", idx+1), fn)
|
t.Run(fmt.Sprintf("Test-%d-prv-%s", idx+1, pn), fn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue