From 61af9f0c8b39b89ea59894c5b4a1f58311709911 Mon Sep 17 00:00:00 2001 From: DarkGopher Date: Fri, 13 Jun 2025 16:19:50 +0200 Subject: [PATCH] xxxxxxx --- session.go | 41 +++++++++--------- storage/file/file.go | 2 - storage/files/files.go | 44 +++++++++++++++++++ storage/memory/memory.go | 92 +++++++++++++++++++++------------------- tests/t_test.go | 4 +- 5 files changed, 118 insertions(+), 65 deletions(-) delete mode 100644 storage/file/file.go create mode 100644 storage/files/files.go diff --git a/session.go b/session.go index 4718eb7..03709db 100644 --- a/session.go +++ b/session.go @@ -32,11 +32,29 @@ func ProviderNames() []string { return prdnames } -// MilisPerSec return time resolution (milliseconds / 1sec) +// MilisPerSec return time resolution (milliseconds / 1sec) changed for short time in testing func MilisPerSec() int64 { 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 type Session interface { //set session value and update last access time @@ -49,22 +67,6 @@ type Session interface { 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. // If Register is called twice with the same name or if driver is nil, it panics. func Register(name string, provide Provider) { @@ -91,13 +93,14 @@ type SessOpts struct { 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) { var prv Provider var ok bool if prv, ok = provides[providerName]; !ok { return nil, fmt.Errorf("session: Provider: %q not found (forgotten import?)", providerName) } + prv.SetParams(adopts) m := &Manager{ provider: prv, sessOpts: sopts, @@ -169,7 +172,7 @@ func (manager *Manager) Exists(sid string) bool { func (manager *Manager) RegenerateID(w http.ResponseWriter, r *http.Request) { if ck, err := r.Cookie(manager.sessOpts.CookieName); err == nil && ck.Value != "" { if newid, err := manager.sessionID(); err != nil { - manager.provider.RegenerateID(ck.Value, newid) + manager.provider.ChangeID(ck.Value, newid) } } } diff --git a/storage/file/file.go b/storage/file/file.go deleted file mode 100644 index 502df50..0000000 --- a/storage/file/file.go +++ /dev/null @@ -1,2 +0,0 @@ -// Package file implements sessions saved into filesystem persistently encoded using gob -package file diff --git a/storage/files/files.go b/storage/files/files.go new file mode 100644 index 0000000..3b479da --- /dev/null +++ b/storage/files/files.go @@ -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 +} diff --git a/storage/memory/memory.go b/storage/memory/memory.go index aa6216b..60357b5 100644 --- a/storage/memory/memory.go +++ b/storage/memory/memory.go @@ -3,6 +3,7 @@ package memory import ( "container/list" + "fmt" "sync" "time" @@ -16,47 +17,6 @@ func init() { 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 type ProviderMemory struct { 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 func (pder *ProviderMemory) Init(sid string) (ses session.Session, err error) { pder.lock.Lock() @@ -114,8 +79,8 @@ func (pder *ProviderMemory) Destroy(sid string) (err error) { return } -// RegenerateID replace session ID to new one and preserve all data -func (pder *ProviderMemory) RegenerateID(oldsid, newsid string) (err error) { +// ChangeID replace session ID to new one and preserve all data +func (pder *ProviderMemory) ChangeID(oldsid, newsid string) (err error) { pder.lock.Lock() defer pder.lock.Unlock() 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 +} diff --git a/tests/t_test.go b/tests/t_test.go index 9efe986..433402d 100644 --- a/tests/t_test.go +++ b/tests/t_test.go @@ -287,6 +287,7 @@ func TestRunAll(t *testing.T) { var err error jar, _ := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List}) testclient.Jar = jar + sessopts := &session.SessOpts{ CookieName: sid, MaxLifetime: 180, Ssl: true, @@ -295,9 +296,10 @@ func TestRunAll(t *testing.T) { if sm, err = session.NewManager(pn, sessopts, nil); err != nil { 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} 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) } } }