diff --git a/go.mod b/go.mod index dc71fae..cf04a84 100644 --- a/go.mod +++ b/go.mod @@ -1,9 +1,10 @@ -module github.com/go-session/session/v3 +module github.com/mbict/session -go 1.17 +go 1.21 require ( - github.com/bytedance/gopkg v0.0.0-20221122125632-68358b8ecec6 + github.com/bytedance/gopkg v0.0.0-20230728082804-614d0af6619b + github.com/google/uuid v1.4.0 github.com/smartystreets/goconvey v1.6.4 ) diff --git a/go.sum b/go.sum index 49172dc..85e49ea 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,8 @@ -github.com/bytedance/gopkg v0.0.0-20221122125632-68358b8ecec6 h1:FCLDGi1EmB7JzjVVYNZiqc/zAJj2BQ5M0lfkVOxbfs8= -github.com/bytedance/gopkg v0.0.0-20221122125632-68358b8ecec6/go.mod h1:5FoAH5xUHHCMDvQPy1rnj8moqLkLHFaDVBjHhcFwEi0= +github.com/bytedance/gopkg v0.0.0-20230728082804-614d0af6619b h1:R6PWoQtxEMpWJPHnpci+9LgFxCS7iJCfOGBvCgZeTKI= +github.com/bytedance/gopkg v0.0.0-20230728082804-614d0af6619b/go.mod h1:FtQG3YbQG9L/91pbKSw787yBQPutC+457AvDW77fgUQ= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 h1:l5lAOZEym3oK3SQ2HBHWsJUfbNBiTXJDeW2QDxw9AQ0= github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= @@ -16,10 +18,15 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/session.go b/session.go index 1c3e11b..791e4e1 100644 --- a/session.go +++ b/session.go @@ -293,6 +293,25 @@ func (m *Manager) setCookie(sessionID string, w http.ResponseWriter, r *http.Req } } +// Check will only resume a session, not create it if it doesn't exists +func (m *Manager) Check(ctx context.Context, w http.ResponseWriter, r *http.Request) (Store, error) { + ctx = m.getContext(ctx, w, r) + + sid, err := m.sessionID(r) + if err != nil { + return nil, err + } + + if sid != "" { + if exists, err := m.opts.store.Check(ctx, sid); err != nil { + return nil, err + } else if exists { + return m.opts.store.Update(ctx, sid, m.opts.expired) + } + } + return nil, nil +} + // Start a session and return to session storage func (m *Manager) Start(ctx context.Context, w http.ResponseWriter, r *http.Request) (Store, error) { ctx = m.getContext(ctx, w, r) @@ -345,6 +364,26 @@ func (m *Manager) Refresh(ctx context.Context, w http.ResponseWriter, r *http.Re func (m *Manager) Destroy(ctx context.Context, w http.ResponseWriter, r *http.Request) error { ctx = m.getContext(ctx, w, r) + defer func() { + if m.opts.enableSetCookie { + cookie := &http.Cookie{ + Name: m.opts.cookieName, + Path: "/", + HttpOnly: true, + Expires: time.Now(), + MaxAge: -1, + } + + http.SetCookie(w, cookie) + } + + if m.opts.enableSIDInHTTPHeader { + key := m.opts.sessionNameInHTTPHeader + r.Header.Del(key) + w.Header().Del(key) + } + }() + sid, err := m.sessionID(r) if err != nil { return err @@ -363,23 +402,5 @@ func (m *Manager) Destroy(ctx context.Context, w http.ResponseWriter, r *http.Re return err } - if m.opts.enableSetCookie { - cookie := &http.Cookie{ - Name: m.opts.cookieName, - Path: "/", - HttpOnly: true, - Expires: time.Now(), - MaxAge: -1, - } - - http.SetCookie(w, cookie) - } - - if m.opts.enableSIDInHTTPHeader { - key := m.opts.sessionNameInHTTPHeader - r.Header.Del(key) - w.Header().Del(key) - } - return nil } diff --git a/store.go b/store.go index da60210..c9bf849 100644 --- a/store.go +++ b/store.go @@ -6,6 +6,7 @@ import ( "time" "github.com/bytedance/gopkg/collection/skipmap" + "github.com/google/uuid" ) var ( @@ -40,6 +41,14 @@ type Store interface { Set(key string, value interface{}) // Get session value Get(key string) (interface{}, bool) + // GetString get session value as a string + GetString(key string) (string, bool) + // GetInt get session value as a integer + GetInt(key string) (int, bool) + // GetBool get session value as a boolean + GetBool(key string) (bool, bool) + // GetUUID get session value as a UUID + GetUUID(key string) (uuid.UUID, bool) // Delete session value, call save function to take effect Delete(key string) interface{} // Save session data @@ -197,6 +206,48 @@ func (s *store) Get(key string) (interface{}, bool) { return val, ok } +func (s *store) GetString(key string) (string, bool) { + if v, ok := s.Get(key); ok { + str, ok := v.(string) + return str, ok + } + return "", false +} + +func (s *store) GetBool(key string) (bool, bool) { + if v, ok := s.Get(key); ok { + b, ok := v.(bool) + return b, ok + } + return false, false +} + +func (s *store) GetInt(key string) (int, bool) { + if v, ok := s.Get(key); ok { + i, ok := v.(int) + return i, ok + } + return 0, false +} + +func (s *store) GetUUID(key string) (uuid.UUID, bool) { + if v, ok := s.Get(key); ok { + switch t := v.(type) { + case uuid.UUID: + return t, true + case string: + if id, err := uuid.Parse(t); err == nil { + return id, true + } + case []byte: + if id, err := uuid.FromBytes(t); err == nil { + return id, true + } + } + } + return uuid.Nil, false +} + func (s *store) Delete(key string) interface{} { s.RLock() v, ok := s.values[key]