From 84f333210a31953ee5e24f3dc1b42a5a1c8e145b Mon Sep 17 00:00:00 2001 From: swh Date: Thu, 18 Feb 2016 16:44:42 +0800 Subject: [PATCH 01/38] fix -- for echo framework --- sessions.go | 26 +++++++++++++------------- store.go | 35 ++++++++++++++++++----------------- 2 files changed, 31 insertions(+), 30 deletions(-) diff --git a/sessions.go b/sessions.go index d6bfb6e..b6db0e1 100644 --- a/sessions.go +++ b/sessions.go @@ -10,7 +10,7 @@ import ( "net/http" "time" - "github.com/gorilla/context" + "github.com/webx-top/echo" ) // Default flashes key. @@ -90,8 +90,8 @@ func (s *Session) AddFlash(value interface{}, vars ...string) { // Save is a convenience method to save this session. It is the same as calling // store.Save(request, response, session). You should call Save before writing to // the response or returning from the handler. -func (s *Session) Save(r *http.Request, w http.ResponseWriter) error { - return s.store.Save(r, w, s) +func (s *Session) Save(ctx echo.Context) error { + return s.store.Save(ctx, s) } // Name returns the name used to register the session. @@ -119,22 +119,22 @@ type contextKey int const registryKey contextKey = 0 // GetRegistry returns a registry instance for the current request. -func GetRegistry(r *http.Request) *Registry { - registry := context.Get(r, registryKey) +func GetRegistry(context echo.Context) *Registry { + registry := context.Get(registryKey) if registry != nil { return registry.(*Registry) } newRegistry := &Registry{ - request: r, + context: context, sessions: make(map[string]sessionInfo), } - context.Set(r, registryKey, newRegistry) + context.Set(registryKey, newRegistry) return newRegistry } // Registry stores sessions used during a request. type Registry struct { - request *http.Request + context echo.Context sessions map[string]sessionInfo } @@ -145,7 +145,7 @@ func (s *Registry) Get(store Store, name string) (session *Session, err error) { if info, ok := s.sessions[name]; ok { session, err = info.s, info.e } else { - session, err = store.New(s.request, name) + session, err = store.New(s.context, name) session.name = name s.sessions[name] = sessionInfo{s: session, e: err} } @@ -154,14 +154,14 @@ func (s *Registry) Get(store Store, name string) (session *Session, err error) { } // Save saves all sessions registered for the current request. -func (s *Registry) Save(w http.ResponseWriter) error { +func (s *Registry) Save() error { var errMulti MultiError for name, info := range s.sessions { session := info.s if session.store == nil { errMulti = append(errMulti, fmt.Errorf( "sessions: missing store for session %q", name)) - } else if err := session.store.Save(s.request, w, session); err != nil { + } else if err := session.store.Save(s.context, session); err != nil { errMulti = append(errMulti, fmt.Errorf( "sessions: error saving session %q -- %v", name, err)) } @@ -179,8 +179,8 @@ func init() { } // Save saves all sessions used during the current request. -func Save(r *http.Request, w http.ResponseWriter) error { - return GetRegistry(r).Save(w) +func Save(ctx echo.Context) error { + return GetRegistry(ctx).Save() } // NewCookie returns an http.Cookie with the options set. It also sets diff --git a/store.go b/store.go index ba3b9e9..a279d53 100644 --- a/store.go +++ b/store.go @@ -14,6 +14,7 @@ import ( "sync" "github.com/gorilla/securecookie" + "github.com/webx-top/echo" ) // Store is an interface for custom session stores. @@ -21,16 +22,16 @@ import ( // See CookieStore and FilesystemStore for examples. type Store interface { // Get should return a cached session. - Get(r *http.Request, name string) (*Session, error) + Get(ctx echo.Context, name string) (*Session, error) // New should create and return a new session. // // Note that New should never return a nil session, even in the case of // an error if using the Registry infrastructure to cache the session. - New(r *http.Request, name string) (*Session, error) + New(ctx echo.Context, name string) (*Session, error) // Save should persist session to the underlying store implementation. - Save(r *http.Request, w http.ResponseWriter, s *Session) error + Save(ctx echo.Context, s *Session) error } // CookieStore ---------------------------------------------------------------- @@ -76,8 +77,8 @@ type CookieStore struct { // // It returns a new session and an error if the session exists but could // not be decoded. -func (s *CookieStore) Get(r *http.Request, name string) (*Session, error) { - return GetRegistry(r).Get(s, name) +func (s *CookieStore) Get(ctx echo.Context, name string) (*Session, error) { + return GetRegistry(ctx).Get(s, name) } // New returns a session for the given name without adding it to the registry. @@ -85,14 +86,14 @@ func (s *CookieStore) Get(r *http.Request, name string) (*Session, error) { // The difference between New() and Get() is that calling New() twice will // decode the session data twice, while Get() registers and reuses the same // decoded session after the first call. -func (s *CookieStore) New(r *http.Request, name string) (*Session, error) { +func (s *CookieStore) New(ctx echo.Context, name string) (*Session, error) { session := NewSession(s, name) opts := *s.Options session.Options = &opts session.IsNew = true var err error - if c, errCookie := r.Cookie(name); errCookie == nil { - err = securecookie.DecodeMulti(name, c.Value, &session.Values, + if v := ctx.Request().Cookie(name); v != `` { + err = securecookie.DecodeMulti(name, v, &session.Values, s.Codecs...) if err == nil { session.IsNew = false @@ -102,14 +103,14 @@ func (s *CookieStore) New(r *http.Request, name string) (*Session, error) { } // Save adds a single session to the response. -func (s *CookieStore) Save(r *http.Request, w http.ResponseWriter, +func (s *CookieStore) Save(ctx echo.Context, session *Session) error { encoded, err := securecookie.EncodeMulti(session.Name(), session.Values, s.Codecs...) if err != nil { return err } - http.SetCookie(w, NewCookie(session.Name(), encoded, session.Options)) + ctx.Response().SetCookie(NewCookie(session.Name(), encoded, session.Options)) return nil } @@ -179,21 +180,21 @@ func (s *FilesystemStore) MaxLength(l int) { // Get returns a session for the given name after adding it to the registry. // // See CookieStore.Get(). -func (s *FilesystemStore) Get(r *http.Request, name string) (*Session, error) { - return GetRegistry(r).Get(s, name) +func (s *FilesystemStore) Get(ctx echo.Context, name string) (*Session, error) { + return GetRegistry(ctx).Get(s, name) } // New returns a session for the given name without adding it to the registry. // // See CookieStore.New(). -func (s *FilesystemStore) New(r *http.Request, name string) (*Session, error) { +func (s *FilesystemStore) New(ctx echo.Context, name string) (*Session, error) { session := NewSession(s, name) opts := *s.Options session.Options = &opts session.IsNew = true var err error - if c, errCookie := r.Cookie(name); errCookie == nil { - err = securecookie.DecodeMulti(name, c.Value, &session.ID, s.Codecs...) + if v := ctx.Request().Cookie(name); v != `` { + err = securecookie.DecodeMulti(name, v, &session.ID, s.Codecs...) if err == nil { err = s.load(session) if err == nil { @@ -205,7 +206,7 @@ func (s *FilesystemStore) New(r *http.Request, name string) (*Session, error) { } // Save adds a single session to the response. -func (s *FilesystemStore) Save(r *http.Request, w http.ResponseWriter, +func (s *FilesystemStore) Save(ctx echo.Context, session *Session) error { if session.ID == "" { // Because the ID is used in the filename, encode it to @@ -222,7 +223,7 @@ func (s *FilesystemStore) Save(r *http.Request, w http.ResponseWriter, if err != nil { return err } - http.SetCookie(w, NewCookie(session.Name(), encoded, session.Options)) + ctx.Response().SetCookie(NewCookie(session.Name(), encoded, session.Options)) return nil } From 56d6ae1dcfd0714b25b3b682a40b67d9542445ee Mon Sep 17 00:00:00 2001 From: Wenhui Shen Date: Thu, 18 Feb 2016 21:29:43 +0800 Subject: [PATCH 02/38] update --- sessions.go | 4 +++- store.go | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/sessions.go b/sessions.go index b6db0e1..39930cf 100644 --- a/sessions.go +++ b/sessions.go @@ -116,7 +116,9 @@ type sessionInfo struct { type contextKey int // registryKey is the key used to store the registry in the context. -const registryKey contextKey = 0 +//const registryKey contextKey = 0 + +const registryKey = `webx:sessionsRegistry` // GetRegistry returns a registry instance for the current request. func GetRegistry(context echo.Context) *Registry { diff --git a/store.go b/store.go index a279d53..88d2e65 100644 --- a/store.go +++ b/store.go @@ -7,7 +7,6 @@ package sessions import ( "encoding/base32" "io/ioutil" - "net/http" "os" "path/filepath" "strings" From 7ce48c6de5e67f5ec9aa46e6cad2432addb49149 Mon Sep 17 00:00:00 2001 From: Wenhui Shen Date: Fri, 19 Feb 2016 22:37:21 +0800 Subject: [PATCH 03/38] update --- sessions.go | 26 +++++++++++++------------- store.go | 21 +++++++++++---------- 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/sessions.go b/sessions.go index 39930cf..38d486a 100644 --- a/sessions.go +++ b/sessions.go @@ -11,6 +11,7 @@ import ( "time" "github.com/webx-top/echo" + "github.com/webx-top/echo/engine" ) // Default flashes key. @@ -91,7 +92,7 @@ func (s *Session) AddFlash(value interface{}, vars ...string) { // store.Save(request, response, session). You should call Save before writing to // the response or returning from the handler. func (s *Session) Save(ctx echo.Context) error { - return s.store.Save(ctx, s) + return s.store.Save(ctx.Request(), ctx.Response(), s) } // Name returns the name used to register the session. @@ -116,27 +117,26 @@ type sessionInfo struct { type contextKey int // registryKey is the key used to store the registry in the context. -//const registryKey contextKey = 0 - -const registryKey = `webx:sessionsRegistry` +const registryKey contextKey = 0 // GetRegistry returns a registry instance for the current request. -func GetRegistry(context echo.Context) *Registry { - registry := context.Get(registryKey) +func GetRegistry(ctx echo.Context) *Registry { + r := ctx.Request() + registry := engine.Get(r, registryKey) if registry != nil { return registry.(*Registry) } newRegistry := &Registry{ - context: context, + request: r, sessions: make(map[string]sessionInfo), } - context.Set(registryKey, newRegistry) + engine.Set(r, registryKey, newRegistry) return newRegistry } // Registry stores sessions used during a request. type Registry struct { - context echo.Context + request engine.Request sessions map[string]sessionInfo } @@ -147,7 +147,7 @@ func (s *Registry) Get(store Store, name string) (session *Session, err error) { if info, ok := s.sessions[name]; ok { session, err = info.s, info.e } else { - session, err = store.New(s.context, name) + session, err = store.New(s.request, name) session.name = name s.sessions[name] = sessionInfo{s: session, e: err} } @@ -156,14 +156,14 @@ func (s *Registry) Get(store Store, name string) (session *Session, err error) { } // Save saves all sessions registered for the current request. -func (s *Registry) Save() error { +func (s *Registry) Save(w engine.Response) error { var errMulti MultiError for name, info := range s.sessions { session := info.s if session.store == nil { errMulti = append(errMulti, fmt.Errorf( "sessions: missing store for session %q", name)) - } else if err := session.store.Save(s.context, session); err != nil { + } else if err := session.store.Save(s.request, w, session); err != nil { errMulti = append(errMulti, fmt.Errorf( "sessions: error saving session %q -- %v", name, err)) } @@ -182,7 +182,7 @@ func init() { // Save saves all sessions used during the current request. func Save(ctx echo.Context) error { - return GetRegistry(ctx).Save() + return GetRegistry(ctx).Save(ctx.Response()) } // NewCookie returns an http.Cookie with the options set. It also sets diff --git a/store.go b/store.go index 88d2e65..3940d26 100644 --- a/store.go +++ b/store.go @@ -14,6 +14,7 @@ import ( "github.com/gorilla/securecookie" "github.com/webx-top/echo" + "github.com/webx-top/echo/engine" ) // Store is an interface for custom session stores. @@ -27,10 +28,10 @@ type Store interface { // // Note that New should never return a nil session, even in the case of // an error if using the Registry infrastructure to cache the session. - New(ctx echo.Context, name string) (*Session, error) + New(r engine.Request, name string) (*Session, error) // Save should persist session to the underlying store implementation. - Save(ctx echo.Context, s *Session) error + Save(r engine.Request, w engine.Response, s *Session) error } // CookieStore ---------------------------------------------------------------- @@ -85,13 +86,13 @@ func (s *CookieStore) Get(ctx echo.Context, name string) (*Session, error) { // The difference between New() and Get() is that calling New() twice will // decode the session data twice, while Get() registers and reuses the same // decoded session after the first call. -func (s *CookieStore) New(ctx echo.Context, name string) (*Session, error) { +func (s *CookieStore) New(r engine.Request, name string) (*Session, error) { session := NewSession(s, name) opts := *s.Options session.Options = &opts session.IsNew = true var err error - if v := ctx.Request().Cookie(name); v != `` { + if v := r.Cookie(name); v != `` { err = securecookie.DecodeMulti(name, v, &session.Values, s.Codecs...) if err == nil { @@ -102,14 +103,14 @@ func (s *CookieStore) New(ctx echo.Context, name string) (*Session, error) { } // Save adds a single session to the response. -func (s *CookieStore) Save(ctx echo.Context, +func (s *CookieStore) Save(r engine.Request, w engine.Response, session *Session) error { encoded, err := securecookie.EncodeMulti(session.Name(), session.Values, s.Codecs...) if err != nil { return err } - ctx.Response().SetCookie(NewCookie(session.Name(), encoded, session.Options)) + w.SetCookie(NewCookie(session.Name(), encoded, session.Options)) return nil } @@ -186,13 +187,13 @@ func (s *FilesystemStore) Get(ctx echo.Context, name string) (*Session, error) { // New returns a session for the given name without adding it to the registry. // // See CookieStore.New(). -func (s *FilesystemStore) New(ctx echo.Context, name string) (*Session, error) { +func (s *FilesystemStore) New(r engine.Request, name string) (*Session, error) { session := NewSession(s, name) opts := *s.Options session.Options = &opts session.IsNew = true var err error - if v := ctx.Request().Cookie(name); v != `` { + if v := r.Cookie(name); v != `` { err = securecookie.DecodeMulti(name, v, &session.ID, s.Codecs...) if err == nil { err = s.load(session) @@ -205,7 +206,7 @@ func (s *FilesystemStore) New(ctx echo.Context, name string) (*Session, error) { } // Save adds a single session to the response. -func (s *FilesystemStore) Save(ctx echo.Context, +func (s *FilesystemStore) Save(r engine.Request, w engine.Response, session *Session) error { if session.ID == "" { // Because the ID is used in the filename, encode it to @@ -222,7 +223,7 @@ func (s *FilesystemStore) Save(ctx echo.Context, if err != nil { return err } - ctx.Response().SetCookie(NewCookie(session.Name(), encoded, session.Options)) + w.SetCookie(NewCookie(session.Name(), encoded, session.Options)) return nil } From 793a11a5b02a3dded19b557be93d2732c3aad9f0 Mon Sep 17 00:00:00 2001 From: swh Date: Thu, 20 Apr 2017 14:44:54 +0800 Subject: [PATCH 04/38] update --- doc.go | 45 ++++++----- sessions.go | 45 ++++++----- sessions_test.go | 197 ----------------------------------------------- store.go | 24 +++--- store_test.go | 73 ------------------ 5 files changed, 61 insertions(+), 323 deletions(-) delete mode 100644 sessions_test.go delete mode 100644 store_test.go diff --git a/doc.go b/doc.go index b03975f..19ab4c7 100644 --- a/doc.go +++ b/doc.go @@ -22,26 +22,26 @@ The key features are: Let's start with an example that shows the sessions API in a nutshell: import ( - "net/http" - "github.com/gorilla/sessions" + "github.com/admpub/sessions" + "github.com/webx-top/echo" ) var store = sessions.NewCookieStore([]byte("something-very-secret")) - func MyHandler(w http.ResponseWriter, r *http.Request) { + func MyHandler(ctx echo.Context) error { // Get a session. We're ignoring the error resulted from decoding an // existing session: Get() always returns a session, even if empty. - session, err := store.Get(r, "session-name") + session, err := store.Get(ctx, "session-name") if err != nil { - http.Error(w, err.Error(), 500) - return + return err } // Set some session values. session.Values["foo"] = "bar" session.Values[42] = 43 // Save it before we write to the response/return from the handler. - session.Save(r, w) + session.Save(ctx) + return nil } First we initialize a session store calling NewCookieStore() and passing a @@ -72,12 +72,11 @@ Ruby On Rails a few years back. When we request a flash message, it is removed from the session. To add a flash, call session.AddFlash(), and to get all flashes, call session.Flashes(). Here is an example: - func MyHandler(w http.ResponseWriter, r *http.Request) { + func MyHandler(ctx echo.Context) error { // Get a session. - session, err := store.Get(r, "session-name") + session, err := store.Get(ctx, "session-name") if err != nil { - http.Error(w, err.Error(), 500) - return + return error } // Get the previously flashes, if any. @@ -87,7 +86,8 @@ flashes, call session.Flashes(). Here is an example: // Set a new flash. session.AddFlash("Hello, flash messages world!") } - session.Save(r, w) + session.Save(ctx) + return nil } Flash messages are useful to set information to be read after a redirection, @@ -99,7 +99,8 @@ so it is easy to register new datatypes for storage in sessions: import( "encoding/gob" - "github.com/gorilla/sessions" + "github.com/admpub/sessions" + "github.com/webx-top/echo" ) type Person struct { @@ -126,11 +127,10 @@ values of those types to and from our sessions. Note that because session values are stored in a map[string]interface{}, there's a need to type-assert data when retrieving it. We'll use the Person struct we registered above: - func MyHandler(w http.ResponseWriter, r *http.Request) { - session, err := store.Get(r, "session-name") + func MyHandler(ctx echo.Context) error { + session, err := store.Get(ctx, "session-name") if err != nil { - http.Error(w, err.Error(), 500) - return + return err } // Retrieve our struct and type-assert it @@ -141,6 +141,8 @@ a need to type-assert data when retrieving it. We'll use the Person struct we re } // Now we can use our person object + + return nil } By default, session cookies last for a month. This is probably too long for @@ -182,15 +184,16 @@ at once: it's sessions.Save(). Here's an example: var store = sessions.NewCookieStore([]byte("something-very-secret")) - func MyHandler(w http.ResponseWriter, r *http.Request) { + func MyHandler(ctx echo.Context) error { // Get a session and set a value. - session1, _ := store.Get(r, "session-one") + session1, _ := store.Get(ctx, "session-one") session1.Values["foo"] = "bar" // Get another session and set another value. - session2, _ := store.Get(r, "session-two") + session2, _ := store.Get(ctx, "session-two") session2.Values[42] = 43 // Save all sessions. - sessions.Save(r, w) + sessions.Save(ctx) + return nil } This is possible because when we call Get() from a session store, it adds the diff --git a/sessions.go b/sessions.go index 38d486a..a4d019d 100644 --- a/sessions.go +++ b/sessions.go @@ -11,7 +11,6 @@ import ( "time" "github.com/webx-top/echo" - "github.com/webx-top/echo/engine" ) // Default flashes key. @@ -92,7 +91,7 @@ func (s *Session) AddFlash(value interface{}, vars ...string) { // store.Save(request, response, session). You should call Save before writing to // the response or returning from the handler. func (s *Session) Save(ctx echo.Context) error { - return s.store.Save(ctx.Request(), ctx.Response(), s) + return s.store.Save(ctx, s) } // Name returns the name used to register the session. @@ -113,30 +112,26 @@ type sessionInfo struct { e error } -// contextKey is the type used to store the registry in the context. -type contextKey int - // registryKey is the key used to store the registry in the context. -const registryKey contextKey = 0 +const registryKey = `webx:mw.sessions` // GetRegistry returns a registry instance for the current request. func GetRegistry(ctx echo.Context) *Registry { - r := ctx.Request() - registry := engine.Get(r, registryKey) - if registry != nil { - return registry.(*Registry) + registry, ok := ctx.Get(registryKey).(*Registry) + if ok { + return registry } - newRegistry := &Registry{ - request: r, + registry = &Registry{ + context: ctx, sessions: make(map[string]sessionInfo), } - engine.Set(r, registryKey, newRegistry) - return newRegistry + ctx.Set(registryKey, registry) + return registry } // Registry stores sessions used during a request. type Registry struct { - request engine.Request + context echo.Context sessions map[string]sessionInfo } @@ -147,7 +142,7 @@ func (s *Registry) Get(store Store, name string) (session *Session, err error) { if info, ok := s.sessions[name]; ok { session, err = info.s, info.e } else { - session, err = store.New(s.request, name) + session, err = store.New(s.context, name) session.name = name s.sessions[name] = sessionInfo{s: session, e: err} } @@ -156,14 +151,14 @@ func (s *Registry) Get(store Store, name string) (session *Session, err error) { } // Save saves all sessions registered for the current request. -func (s *Registry) Save(w engine.Response) error { +func (s *Registry) Save(ctx echo.Context) error { var errMulti MultiError for name, info := range s.sessions { session := info.s if session.store == nil { errMulti = append(errMulti, fmt.Errorf( "sessions: missing store for session %q", name)) - } else if err := session.store.Save(s.request, w, session); err != nil { + } else if err := session.store.Save(ctx, session); err != nil { errMulti = append(errMulti, fmt.Errorf( "sessions: error saving session %q -- %v", name, err)) } @@ -182,7 +177,7 @@ func init() { // Save saves all sessions used during the current request. func Save(ctx echo.Context) error { - return GetRegistry(ctx).Save(ctx.Response()) + return GetRegistry(ctx).Save(ctx) } // NewCookie returns an http.Cookie with the options set. It also sets @@ -208,6 +203,18 @@ func NewCookie(name, value string, options *Options) *http.Cookie { return cookie } +// SetCookie for echo +func SetCookie(ctx echo.Context, key string, value string, options *Options) { + ctx.SetCookie( + key, value, + options.MaxAge, + options.Path, + options.Domain, + options.Secure, + options.HttpOnly, + ) +} + // Error ---------------------------------------------------------------------- // MultiError stores multiple errors. diff --git a/sessions_test.go b/sessions_test.go deleted file mode 100644 index fcc69eb..0000000 --- a/sessions_test.go +++ /dev/null @@ -1,197 +0,0 @@ -// Copyright 2012 The Gorilla Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package sessions - -import ( - "bytes" - "encoding/gob" - "net/http" - "testing" -) - -// ---------------------------------------------------------------------------- -// ResponseRecorder -// ---------------------------------------------------------------------------- -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// ResponseRecorder is an implementation of http.ResponseWriter that -// records its mutations for later inspection in tests. -type ResponseRecorder struct { - Code int // the HTTP response code from WriteHeader - HeaderMap http.Header // the HTTP response headers - Body *bytes.Buffer // if non-nil, the bytes.Buffer to append written data to - Flushed bool -} - -// NewRecorder returns an initialized ResponseRecorder. -func NewRecorder() *ResponseRecorder { - return &ResponseRecorder{ - HeaderMap: make(http.Header), - Body: new(bytes.Buffer), - } -} - -// DefaultRemoteAddr is the default remote address to return in RemoteAddr if -// an explicit DefaultRemoteAddr isn't set on ResponseRecorder. -const DefaultRemoteAddr = "1.2.3.4" - -// Header returns the response headers. -func (rw *ResponseRecorder) Header() http.Header { - return rw.HeaderMap -} - -// Write always succeeds and writes to rw.Body, if not nil. -func (rw *ResponseRecorder) Write(buf []byte) (int, error) { - if rw.Body != nil { - rw.Body.Write(buf) - } - if rw.Code == 0 { - rw.Code = http.StatusOK - } - return len(buf), nil -} - -// WriteHeader sets rw.Code. -func (rw *ResponseRecorder) WriteHeader(code int) { - rw.Code = code -} - -// Flush sets rw.Flushed to true. -func (rw *ResponseRecorder) Flush() { - rw.Flushed = true -} - -// ---------------------------------------------------------------------------- - -type FlashMessage struct { - Type int - Message string -} - -func TestFlashes(t *testing.T) { - var req *http.Request - var rsp *ResponseRecorder - var hdr http.Header - var err error - var ok bool - var cookies []string - var session *Session - var flashes []interface{} - - store := NewCookieStore([]byte("secret-key")) - - // Round 1 ---------------------------------------------------------------- - - req, _ = http.NewRequest("GET", "http://localhost:8080/", nil) - rsp = NewRecorder() - // Get a session. - if session, err = store.Get(req, "session-key"); err != nil { - t.Fatalf("Error getting session: %v", err) - } - // Get a flash. - flashes = session.Flashes() - if len(flashes) != 0 { - t.Errorf("Expected empty flashes; Got %v", flashes) - } - // Add some flashes. - session.AddFlash("foo") - session.AddFlash("bar") - // Custom key. - session.AddFlash("baz", "custom_key") - // Save. - if err = Save(req, rsp); err != nil { - t.Fatalf("Error saving session: %v", err) - } - hdr = rsp.Header() - cookies, ok = hdr["Set-Cookie"] - if !ok || len(cookies) != 1 { - t.Fatal("No cookies. Header:", hdr) - } - - // Round 2 ---------------------------------------------------------------- - - req, _ = http.NewRequest("GET", "http://localhost:8080/", nil) - req.Header.Add("Cookie", cookies[0]) - rsp = NewRecorder() - // Get a session. - if session, err = store.Get(req, "session-key"); err != nil { - t.Fatalf("Error getting session: %v", err) - } - // Check all saved values. - flashes = session.Flashes() - if len(flashes) != 2 { - t.Fatalf("Expected flashes; Got %v", flashes) - } - if flashes[0] != "foo" || flashes[1] != "bar" { - t.Errorf("Expected foo,bar; Got %v", flashes) - } - flashes = session.Flashes() - if len(flashes) != 0 { - t.Errorf("Expected dumped flashes; Got %v", flashes) - } - // Custom key. - flashes = session.Flashes("custom_key") - if len(flashes) != 1 { - t.Errorf("Expected flashes; Got %v", flashes) - } else if flashes[0] != "baz" { - t.Errorf("Expected baz; Got %v", flashes) - } - flashes = session.Flashes("custom_key") - if len(flashes) != 0 { - t.Errorf("Expected dumped flashes; Got %v", flashes) - } - - // Round 3 ---------------------------------------------------------------- - // Custom type - - req, _ = http.NewRequest("GET", "http://localhost:8080/", nil) - rsp = NewRecorder() - // Get a session. - if session, err = store.Get(req, "session-key"); err != nil { - t.Fatalf("Error getting session: %v", err) - } - // Get a flash. - flashes = session.Flashes() - if len(flashes) != 0 { - t.Errorf("Expected empty flashes; Got %v", flashes) - } - // Add some flashes. - session.AddFlash(&FlashMessage{42, "foo"}) - // Save. - if err = Save(req, rsp); err != nil { - t.Fatalf("Error saving session: %v", err) - } - hdr = rsp.Header() - cookies, ok = hdr["Set-Cookie"] - if !ok || len(cookies) != 1 { - t.Fatal("No cookies. Header:", hdr) - } - - // Round 4 ---------------------------------------------------------------- - // Custom type - - req, _ = http.NewRequest("GET", "http://localhost:8080/", nil) - req.Header.Add("Cookie", cookies[0]) - rsp = NewRecorder() - // Get a session. - if session, err = store.Get(req, "session-key"); err != nil { - t.Fatalf("Error getting session: %v", err) - } - // Check all saved values. - flashes = session.Flashes() - if len(flashes) != 1 { - t.Fatalf("Expected flashes; Got %v", flashes) - } - custom := flashes[0].(FlashMessage) - if custom.Type != 42 || custom.Message != "foo" { - t.Errorf("Expected %#v, got %#v", FlashMessage{42, "foo"}, custom) - } -} - -func init() { - gob.Register(FlashMessage{}) -} diff --git a/store.go b/store.go index 3940d26..4992482 100644 --- a/store.go +++ b/store.go @@ -14,7 +14,6 @@ import ( "github.com/gorilla/securecookie" "github.com/webx-top/echo" - "github.com/webx-top/echo/engine" ) // Store is an interface for custom session stores. @@ -28,10 +27,10 @@ type Store interface { // // Note that New should never return a nil session, even in the case of // an error if using the Registry infrastructure to cache the session. - New(r engine.Request, name string) (*Session, error) + New(ctx echo.Context, name string) (*Session, error) // Save should persist session to the underlying store implementation. - Save(r engine.Request, w engine.Response, s *Session) error + Save(ctx echo.Context, s *Session) error } // CookieStore ---------------------------------------------------------------- @@ -86,13 +85,13 @@ func (s *CookieStore) Get(ctx echo.Context, name string) (*Session, error) { // The difference between New() and Get() is that calling New() twice will // decode the session data twice, while Get() registers and reuses the same // decoded session after the first call. -func (s *CookieStore) New(r engine.Request, name string) (*Session, error) { +func (s *CookieStore) New(ctx echo.Context, name string) (*Session, error) { session := NewSession(s, name) opts := *s.Options session.Options = &opts session.IsNew = true var err error - if v := r.Cookie(name); v != `` { + if v := ctx.Request().Cookie(name); len(v) > 0 { err = securecookie.DecodeMulti(name, v, &session.Values, s.Codecs...) if err == nil { @@ -103,14 +102,13 @@ func (s *CookieStore) New(r engine.Request, name string) (*Session, error) { } // Save adds a single session to the response. -func (s *CookieStore) Save(r engine.Request, w engine.Response, - session *Session) error { +func (s *CookieStore) Save(ctx echo.Context, session *Session) error { encoded, err := securecookie.EncodeMulti(session.Name(), session.Values, s.Codecs...) if err != nil { return err } - w.SetCookie(NewCookie(session.Name(), encoded, session.Options)) + SetCookie(ctx, session.Name(), encoded, session.Options) return nil } @@ -187,13 +185,13 @@ func (s *FilesystemStore) Get(ctx echo.Context, name string) (*Session, error) { // New returns a session for the given name without adding it to the registry. // // See CookieStore.New(). -func (s *FilesystemStore) New(r engine.Request, name string) (*Session, error) { +func (s *FilesystemStore) New(ctx echo.Context, name string) (*Session, error) { session := NewSession(s, name) opts := *s.Options session.Options = &opts session.IsNew = true var err error - if v := r.Cookie(name); v != `` { + if v := ctx.Request().Cookie(name); len(v) > 0 { err = securecookie.DecodeMulti(name, v, &session.ID, s.Codecs...) if err == nil { err = s.load(session) @@ -206,9 +204,9 @@ func (s *FilesystemStore) New(r engine.Request, name string) (*Session, error) { } // Save adds a single session to the response. -func (s *FilesystemStore) Save(r engine.Request, w engine.Response, +func (s *FilesystemStore) Save(ctx echo.Context, session *Session) error { - if session.ID == "" { + if len(session.ID) == 0 { // Because the ID is used in the filename, encode it to // use alphanumeric characters only. session.ID = strings.TrimRight( @@ -223,7 +221,7 @@ func (s *FilesystemStore) Save(r engine.Request, w engine.Response, if err != nil { return err } - w.SetCookie(NewCookie(session.Name(), encoded, session.Options)) + SetCookie(ctx, session.Name(), encoded, session.Options) return nil } diff --git a/store_test.go b/store_test.go deleted file mode 100644 index 022acba..0000000 --- a/store_test.go +++ /dev/null @@ -1,73 +0,0 @@ -package sessions - -import ( - "encoding/base64" - "net/http" - "net/http/httptest" - "testing" -) - -// Test for GH-8 for CookieStore -func TestGH8CookieStore(t *testing.T) { - originalPath := "/" - store := NewCookieStore() - store.Options.Path = originalPath - req, err := http.NewRequest("GET", "http://www.example.com", nil) - if err != nil { - t.Fatal("failed to create request", err) - } - - session, err := store.New(req, "hello") - if err != nil { - t.Fatal("failed to create session", err) - } - - store.Options.Path = "/foo" - if session.Options.Path != originalPath { - t.Fatalf("bad session path: got %q, want %q", session.Options.Path, originalPath) - } -} - -// Test for GH-8 for FilesystemStore -func TestGH8FilesystemStore(t *testing.T) { - originalPath := "/" - store := NewFilesystemStore("") - store.Options.Path = originalPath - req, err := http.NewRequest("GET", "http://www.example.com", nil) - if err != nil { - t.Fatal("failed to create request", err) - } - - session, err := store.New(req, "hello") - if err != nil { - t.Fatal("failed to create session", err) - } - - store.Options.Path = "/foo" - if session.Options.Path != originalPath { - t.Fatalf("bad session path: got %q, want %q", session.Options.Path, originalPath) - } -} - -// Test for GH-2. -func TestGH2MaxLength(t *testing.T) { - store := NewFilesystemStore("", []byte("some key")) - req, err := http.NewRequest("GET", "http://www.example.com", nil) - if err != nil { - t.Fatal("failed to create request", err) - } - w := httptest.NewRecorder() - - session, err := store.New(req, "my session") - session.Values["big"] = make([]byte, base64.StdEncoding.DecodedLen(4096*2)) - err = session.Save(req, w) - if err == nil { - t.Fatal("expected an error, got nil") - } - - store.MaxLength(4096 * 3) // A bit more than the value size to account for encoding overhead. - err = session.Save(req, w) - if err != nil { - t.Fatal("failed to Save:", err) - } -} From 9a96fc7c41f2271e80c057640931757eaccc755c Mon Sep 17 00:00:00 2001 From: swh Date: Thu, 20 Apr 2017 16:25:42 +0800 Subject: [PATCH 05/38] fixed bug --- store.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/store.go b/store.go index 4992482..74f4fe1 100644 --- a/store.go +++ b/store.go @@ -91,7 +91,7 @@ func (s *CookieStore) New(ctx echo.Context, name string) (*Session, error) { session.Options = &opts session.IsNew = true var err error - if v := ctx.Request().Cookie(name); len(v) > 0 { + if v := ctx.GetCookie(name); len(v) > 0 { err = securecookie.DecodeMulti(name, v, &session.Values, s.Codecs...) if err == nil { @@ -191,7 +191,7 @@ func (s *FilesystemStore) New(ctx echo.Context, name string) (*Session, error) { session.Options = &opts session.IsNew = true var err error - if v := ctx.Request().Cookie(name); len(v) > 0 { + if v := ctx.GetCookie(name); len(v) > 0 { err = securecookie.DecodeMulti(name, v, &session.ID, s.Codecs...) if err == nil { err = s.load(session) From 67899843326615eb013a1549755bb5b12bef2e70 Mon Sep 17 00:00:00 2001 From: Wenhui Shen Date: Fri, 21 Apr 2017 23:53:14 +0800 Subject: [PATCH 06/38] update --- .vscode/temp.sql | 0 lex.go | 102 +++++++++++++++++++++++++++++++++++++++++++++++ sessions.go | 8 +++- store.go | 18 +++++++++ 4 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 .vscode/temp.sql create mode 100644 lex.go diff --git a/.vscode/temp.sql b/.vscode/temp.sql new file mode 100644 index 0000000..e69de29 diff --git a/lex.go b/lex.go new file mode 100644 index 0000000..4bbbe10 --- /dev/null +++ b/lex.go @@ -0,0 +1,102 @@ +// This file contains code adapted from the Go standard library +// https://github.com/golang/go/blob/39ad0fd0789872f9469167be7fe9578625ff246e/src/net/http/lex.go + +package sessions + +import "strings" + +var isTokenTable = [127]bool{ + '!': true, + '#': true, + '$': true, + '%': true, + '&': true, + '\'': true, + '*': true, + '+': true, + '-': true, + '.': true, + '0': true, + '1': true, + '2': true, + '3': true, + '4': true, + '5': true, + '6': true, + '7': true, + '8': true, + '9': true, + 'A': true, + 'B': true, + 'C': true, + 'D': true, + 'E': true, + 'F': true, + 'G': true, + 'H': true, + 'I': true, + 'J': true, + 'K': true, + 'L': true, + 'M': true, + 'N': true, + 'O': true, + 'P': true, + 'Q': true, + 'R': true, + 'S': true, + 'T': true, + 'U': true, + 'W': true, + 'V': true, + 'X': true, + 'Y': true, + 'Z': true, + '^': true, + '_': true, + '`': true, + 'a': true, + 'b': true, + 'c': true, + 'd': true, + 'e': true, + 'f': true, + 'g': true, + 'h': true, + 'i': true, + 'j': true, + 'k': true, + 'l': true, + 'm': true, + 'n': true, + 'o': true, + 'p': true, + 'q': true, + 'r': true, + 's': true, + 't': true, + 'u': true, + 'v': true, + 'w': true, + 'x': true, + 'y': true, + 'z': true, + '|': true, + '~': true, +} + +func isToken(r rune) bool { + i := int(r) + return i < len(isTokenTable) && isTokenTable[i] +} + +func isNotToken(r rune) bool { + return !isToken(r) +} + +func isCookieNameValid(raw string) bool { + if raw == "" { + return false + } + return strings.IndexFunc(raw, isNotToken) < 0 +} diff --git a/sessions.go b/sessions.go index a4d019d..115f3ab 100644 --- a/sessions.go +++ b/sessions.go @@ -45,7 +45,10 @@ func NewSession(store Store, name string) *Session { // Session stores the values and optional configuration for a session. type Session struct { - ID string + // The ID of the session, generated by stores. It should not be used for + // user data. + ID string + // Values contains the user-data for the session. Values map[interface{}]interface{} Options *Options IsNew bool @@ -139,6 +142,9 @@ type Registry struct { // // It returns a new session if there are no sessions registered for the name. func (s *Registry) Get(store Store, name string) (session *Session, err error) { + if !isCookieNameValid(name) { + return nil, fmt.Errorf("sessions: invalid character in cookie name: %s", name) + } if info, ok := s.sessions[name]; ok { session, err = info.s, info.e } else { diff --git a/store.go b/store.go index 74f4fe1..33b2e77 100644 --- a/store.go +++ b/store.go @@ -206,6 +206,14 @@ func (s *FilesystemStore) New(ctx echo.Context, name string) (*Session, error) { // Save adds a single session to the response. func (s *FilesystemStore) Save(ctx echo.Context, session *Session) error { + // Delete if max-age is <= 0 + if session.Options.MaxAge <= 0 { + if err := s.erase(session); err != nil { + return err + } + SetCookie(ctx, session.Name(), "", session.Options) + return nil + } if len(session.ID) == 0 { // Because the ID is used in the filename, encode it to // use alphanumeric characters only. @@ -225,6 +233,16 @@ func (s *FilesystemStore) Save(ctx echo.Context, return nil } +// delete session file +func (s *FilesystemStore) erase(session *Session) error { + filename := filepath.Join(s.path, "session_"+session.ID) + fileMutex.RLock() + defer fileMutex.RUnlock() + + err := os.Remove(filename) + return err +} + // MaxAge sets the maximum age for the store and the underlying cookie // implementation. Individual sessions can be deleted by setting Options.MaxAge // = -1 for that session. From 33a965795ae743ec3a0ea7f083780110be5b62ea Mon Sep 17 00:00:00 2001 From: Wenhui Shen Date: Fri, 21 Apr 2017 23:56:18 +0800 Subject: [PATCH 07/38] update --- .gitignore | 1 + .vscode/temp.sql | 0 2 files changed, 1 insertion(+) create mode 100644 .gitignore delete mode 100644 .vscode/temp.sql diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..598ae79 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/.vscode diff --git a/.vscode/temp.sql b/.vscode/temp.sql deleted file mode 100644 index e69de29..0000000 From dc272174175f7f9647ee7184d4eba13ee98859a1 Mon Sep 17 00:00:00 2001 From: Wenhui Shen Date: Sat, 22 Jul 2017 12:28:45 +0800 Subject: [PATCH 08/38] update --- sessions.go | 39 +++++++--------------------------- store.go | 60 ++++++++++++++++++++--------------------------------- 2 files changed, 31 insertions(+), 68 deletions(-) diff --git a/sessions.go b/sessions.go index 115f3ab..2d19c8a 100644 --- a/sessions.go +++ b/sessions.go @@ -16,22 +16,6 @@ import ( // Default flashes key. const flashesKey = "_flash" -// Options -------------------------------------------------------------------- - -// Options stores configuration for a session or session store. -// -// Fields are a subset of http.Cookie fields. -type Options struct { - Path string - Domain string - // MaxAge=0 means no 'Max-Age' attribute specified. - // MaxAge<0 means delete cookie now, equivalently 'Max-Age: 0'. - // MaxAge>0 means Max-Age attribute present and given in seconds. - MaxAge int - Secure bool - HttpOnly bool -} - // Session -------------------------------------------------------------------- // NewSession is called by session stores to create a new session instance. @@ -49,11 +33,10 @@ type Session struct { // user data. ID string // Values contains the user-data for the session. - Values map[interface{}]interface{} - Options *Options - IsNew bool - store Store - name string + Values map[interface{}]interface{} + IsNew bool + store Store + name string } // Flashes returns a slice of flash messages from the session. @@ -189,7 +172,8 @@ func Save(ctx echo.Context) error { // NewCookie returns an http.Cookie with the options set. It also sets // the Expires field calculated based on the MaxAge value, for Internet // Explorer compatibility. -func NewCookie(name, value string, options *Options) *http.Cookie { +func NewCookie(ctx echo.Context, name, value string) *http.Cookie { + options := ctx.CookieOptions() cookie := &http.Cookie{ Name: name, Value: value, @@ -210,15 +194,8 @@ func NewCookie(name, value string, options *Options) *http.Cookie { } // SetCookie for echo -func SetCookie(ctx echo.Context, key string, value string, options *Options) { - ctx.SetCookie( - key, value, - options.MaxAge, - options.Path, - options.Domain, - options.Secure, - options.HttpOnly, - ) +func SetCookie(ctx echo.Context, key string, value string) { + ctx.SetCookie(key, value) } // Error ---------------------------------------------------------------------- diff --git a/store.go b/store.go index 33b2e77..0641254 100644 --- a/store.go +++ b/store.go @@ -12,7 +12,7 @@ import ( "strings" "sync" - "github.com/gorilla/securecookie" + "github.com/admpub/securecookie" "github.com/webx-top/echo" ) @@ -53,20 +53,13 @@ type Store interface { func NewCookieStore(keyPairs ...[]byte) *CookieStore { cs := &CookieStore{ Codecs: securecookie.CodecsFromPairs(keyPairs...), - Options: &Options{ - Path: "/", - MaxAge: 86400 * 30, - }, } - - cs.MaxAge(cs.Options.MaxAge) return cs } // CookieStore stores sessions using secure cookies. type CookieStore struct { - Codecs []securecookie.Codec - Options *Options // default configuration + Codecs []securecookie.Codec } // Get returns a session for the given name after adding it to the registry. @@ -87,12 +80,12 @@ func (s *CookieStore) Get(ctx echo.Context, name string) (*Session, error) { // decoded session after the first call. func (s *CookieStore) New(ctx echo.Context, name string) (*Session, error) { session := NewSession(s, name) - opts := *s.Options - session.Options = &opts session.IsNew = true var err error if v := ctx.GetCookie(name); len(v) > 0 { - err = securecookie.DecodeMulti(name, v, &session.Values, + err = securecookie.DecodeMultiWithMaxAge( + name, v, &session.Values, + ctx.CookieOptions().MaxAge, s.Codecs...) if err == nil { session.IsNew = false @@ -108,7 +101,7 @@ func (s *CookieStore) Save(ctx echo.Context, session *Session) error { if err != nil { return err } - SetCookie(ctx, session.Name(), encoded, session.Options) + SetCookie(ctx, session.Name(), encoded) return nil } @@ -116,8 +109,6 @@ func (s *CookieStore) Save(ctx echo.Context, session *Session) error { // implementation. Individual sessions can be deleted by setting Options.MaxAge // = -1 for that session. func (s *CookieStore) MaxAge(age int) { - s.Options.MaxAge = age - // Set the maxAge for each securecookie instance. for _, codec := range s.Codecs { if sc, ok := codec.(*securecookie.SecureCookie); ok { @@ -142,14 +133,8 @@ func NewFilesystemStore(path string, keyPairs ...[]byte) *FilesystemStore { } fs := &FilesystemStore{ Codecs: securecookie.CodecsFromPairs(keyPairs...), - Options: &Options{ - Path: "/", - MaxAge: 86400 * 30, - }, - path: path, + path: path, } - - fs.MaxAge(fs.Options.MaxAge) return fs } @@ -159,9 +144,8 @@ func NewFilesystemStore(path string, keyPairs ...[]byte) *FilesystemStore { // // This store is still experimental and not well tested. Feedback is welcome. type FilesystemStore struct { - Codecs []securecookie.Codec - Options *Options // default configuration - path string + Codecs []securecookie.Codec + path string } // MaxLength restricts the maximum length of new sessions to l. @@ -187,14 +171,15 @@ func (s *FilesystemStore) Get(ctx echo.Context, name string) (*Session, error) { // See CookieStore.New(). func (s *FilesystemStore) New(ctx echo.Context, name string) (*Session, error) { session := NewSession(s, name) - opts := *s.Options - session.Options = &opts session.IsNew = true var err error if v := ctx.GetCookie(name); len(v) > 0 { - err = securecookie.DecodeMulti(name, v, &session.ID, s.Codecs...) + err = securecookie.DecodeMultiWithMaxAge( + name, v, &session.ID, + ctx.CookieOptions().MaxAge, + s.Codecs...) if err == nil { - err = s.load(session) + err = s.load(ctx, session) if err == nil { session.IsNew = false } @@ -207,11 +192,11 @@ func (s *FilesystemStore) New(ctx echo.Context, name string) (*Session, error) { func (s *FilesystemStore) Save(ctx echo.Context, session *Session) error { // Delete if max-age is <= 0 - if session.Options.MaxAge <= 0 { + if ctx.CookieOptions().MaxAge <= 0 { if err := s.erase(session); err != nil { return err } - SetCookie(ctx, session.Name(), "", session.Options) + SetCookie(ctx, session.Name(), "") return nil } if len(session.ID) == 0 { @@ -229,7 +214,7 @@ func (s *FilesystemStore) Save(ctx echo.Context, if err != nil { return err } - SetCookie(ctx, session.Name(), encoded, session.Options) + SetCookie(ctx, session.Name(), encoded) return nil } @@ -247,8 +232,6 @@ func (s *FilesystemStore) erase(session *Session) error { // implementation. Individual sessions can be deleted by setting Options.MaxAge // = -1 for that session. func (s *FilesystemStore) MaxAge(age int) { - s.Options.MaxAge = age - // Set the maxAge for each securecookie instance. for _, codec := range s.Codecs { if sc, ok := codec.(*securecookie.SecureCookie); ok { @@ -271,7 +254,7 @@ func (s *FilesystemStore) save(session *Session) error { } // load reads a file and decodes its content into session.Values. -func (s *FilesystemStore) load(session *Session) error { +func (s *FilesystemStore) load(ctx echo.Context, session *Session) error { filename := filepath.Join(s.path, "session_"+session.ID) fileMutex.RLock() defer fileMutex.RUnlock() @@ -279,8 +262,11 @@ func (s *FilesystemStore) load(session *Session) error { if err != nil { return err } - if err = securecookie.DecodeMulti(session.Name(), string(fdata), - &session.Values, s.Codecs...); err != nil { + if err = securecookie.DecodeMultiWithMaxAge( + session.Name(), string(fdata), + &session.Values, + ctx.CookieOptions().MaxAge, + s.Codecs...); err != nil { return err } return nil From 3650830381a19dad9676432160b11790f0638174 Mon Sep 17 00:00:00 2001 From: Hank Shen Date: Thu, 2 May 2019 10:00:41 +0800 Subject: [PATCH 09/38] update --- sessions.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sessions.go b/sessions.go index 2d19c8a..c0139a6 100644 --- a/sessions.go +++ b/sessions.go @@ -194,8 +194,8 @@ func NewCookie(ctx echo.Context, name, value string) *http.Cookie { } // SetCookie for echo -func SetCookie(ctx echo.Context, key string, value string) { - ctx.SetCookie(key, value) +func SetCookie(ctx echo.Context, key string, value string, args ...interface{}) { + ctx.SetCookie(key, value, args...) } // Error ---------------------------------------------------------------------- From d034976064c535b4ff1c2a3af0efc1b2a84af49a Mon Sep 17 00:00:00 2001 From: Hank Shen Date: Thu, 2 May 2019 10:13:40 +0800 Subject: [PATCH 10/38] update --- store.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/store.go b/store.go index 0641254..13d2040 100644 --- a/store.go +++ b/store.go @@ -196,7 +196,7 @@ func (s *FilesystemStore) Save(ctx echo.Context, if err := s.erase(session); err != nil { return err } - SetCookie(ctx, session.Name(), "") + SetCookie(ctx, session.Name(), "", -1) return nil } if len(session.ID) == 0 { From c41aec4c78c6181e3d9b1d4f4333c26c6c7aeed1 Mon Sep 17 00:00:00 2001 From: Hank Shen Date: Thu, 2 May 2019 12:31:38 +0800 Subject: [PATCH 11/38] update --- store.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/store.go b/store.go index 13d2040..30ecfdd 100644 --- a/store.go +++ b/store.go @@ -220,6 +220,9 @@ func (s *FilesystemStore) Save(ctx echo.Context, // delete session file func (s *FilesystemStore) erase(session *Session) error { + if len(session.ID) == 0 { + return nil + } filename := filepath.Join(s.path, "session_"+session.ID) fileMutex.RLock() defer fileMutex.RUnlock() From aadf35331c6e2b5c6749dc37f7b8b7297101fd54 Mon Sep 17 00:00:00 2001 From: Hank Shen Date: Thu, 2 May 2019 13:11:30 +0800 Subject: [PATCH 12/38] update --- store.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/store.go b/store.go index 30ecfdd..cdce23e 100644 --- a/store.go +++ b/store.go @@ -191,8 +191,8 @@ func (s *FilesystemStore) New(ctx echo.Context, name string) (*Session, error) { // Save adds a single session to the response. func (s *FilesystemStore) Save(ctx echo.Context, session *Session) error { - // Delete if max-age is <= 0 - if ctx.CookieOptions().MaxAge <= 0 { + // Delete if max-age is < 0 + if ctx.CookieOptions().MaxAge < 0 { if err := s.erase(session); err != nil { return err } From f83061d6d718ca255de55f64f92fc53203f68d33 Mon Sep 17 00:00:00 2001 From: shen_wen_hui Date: Sun, 5 May 2019 17:59:40 +0800 Subject: [PATCH 13/38] update --- sessions.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/sessions.go b/sessions.go index 2d19c8a..ffdae5c 100644 --- a/sessions.go +++ b/sessions.go @@ -103,15 +103,17 @@ const registryKey = `webx:mw.sessions` // GetRegistry returns a registry instance for the current request. func GetRegistry(ctx echo.Context) *Registry { - registry, ok := ctx.Get(registryKey).(*Registry) - if ok { - return registry + if v, ok := ctx.Internal().Load(registryKey); ok { + registry, ok := v.(*Registry) + if ok { + return registry + } } - registry = &Registry{ + registry := &Registry{ context: ctx, sessions: make(map[string]sessionInfo), } - ctx.Set(registryKey, registry) + ctx.Internal().Store(registryKey, registry) return registry } From 820298e67e38f60df55ebdd80fd8a2b29027beca Mon Sep 17 00:00:00 2001 From: shen_wen_hui Date: Sun, 5 May 2019 18:04:16 +0800 Subject: [PATCH 14/38] update --- sessions.go | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/sessions.go b/sessions.go index ffdae5c..0a318ed 100644 --- a/sessions.go +++ b/sessions.go @@ -103,17 +103,14 @@ const registryKey = `webx:mw.sessions` // GetRegistry returns a registry instance for the current request. func GetRegistry(ctx echo.Context) *Registry { - if v, ok := ctx.Internal().Load(registryKey); ok { - registry, ok := v.(*Registry) - if ok { - return registry - } - } registry := &Registry{ context: ctx, sessions: make(map[string]sessionInfo), } - ctx.Internal().Store(registryKey, registry) + actual, loaded := ctx.Internal().LoadOrStore(registryKey, registry) + if loaded { + registry = actual.(*Registry) + } return registry } From 90473594ee0f2e4dc1c06b0d47b0f98510df3c92 Mon Sep 17 00:00:00 2001 From: Hank Shen Date: Mon, 15 Jun 2020 16:00:32 +0800 Subject: [PATCH 15/38] update --- sessions.go | 1 + store.go | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/sessions.go b/sessions.go index 865d952..dc65b9e 100644 --- a/sessions.go +++ b/sessions.go @@ -193,6 +193,7 @@ func NewCookie(ctx echo.Context, name, value string) *http.Cookie { } // SetCookie for echo +// @param:ctx,key,value,maxAge(seconds),path(/),domain,secure,httpOnly,sameSite(lax/strict/default) func SetCookie(ctx echo.Context, key string, value string, args ...interface{}) { ctx.SetCookie(key, value, args...) } diff --git a/store.go b/store.go index cdce23e..21934bd 100644 --- a/store.go +++ b/store.go @@ -30,7 +30,8 @@ type Store interface { New(ctx echo.Context, name string) (*Session, error) // Save should persist session to the underlying store implementation. - Save(ctx echo.Context, s *Session) error + // @param args:maxAge(seconds),path(/),domain,secure,httpOnly,sameSite(lax/strict/default) + Save(ctx echo.Context, s *Session, args ...interface{}) error } // CookieStore ---------------------------------------------------------------- @@ -95,13 +96,13 @@ func (s *CookieStore) New(ctx echo.Context, name string) (*Session, error) { } // Save adds a single session to the response. -func (s *CookieStore) Save(ctx echo.Context, session *Session) error { +func (s *CookieStore) Save(ctx echo.Context, session *Session, args ...interface{}) error { encoded, err := securecookie.EncodeMulti(session.Name(), session.Values, s.Codecs...) if err != nil { return err } - SetCookie(ctx, session.Name(), encoded) + SetCookie(ctx, session.Name(), encoded, args...) return nil } @@ -189,8 +190,7 @@ func (s *FilesystemStore) New(ctx echo.Context, name string) (*Session, error) { } // Save adds a single session to the response. -func (s *FilesystemStore) Save(ctx echo.Context, - session *Session) error { +func (s *FilesystemStore) Save(ctx echo.Context, session *Session, args ...interface{}) error { // Delete if max-age is < 0 if ctx.CookieOptions().MaxAge < 0 { if err := s.erase(session); err != nil { @@ -214,7 +214,7 @@ func (s *FilesystemStore) Save(ctx echo.Context, if err != nil { return err } - SetCookie(ctx, session.Name(), encoded) + SetCookie(ctx, session.Name(), encoded, args...) return nil } From 61ae93e6ea22407566ba751bae9ef079f89aa646 Mon Sep 17 00:00:00 2001 From: Hank Shen Date: Mon, 15 Jun 2020 16:11:28 +0800 Subject: [PATCH 16/38] update --- sessions.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sessions.go b/sessions.go index dc65b9e..2f20258 100644 --- a/sessions.go +++ b/sessions.go @@ -195,6 +195,9 @@ func NewCookie(ctx echo.Context, name, value string) *http.Cookie { // SetCookie for echo // @param:ctx,key,value,maxAge(seconds),path(/),domain,secure,httpOnly,sameSite(lax/strict/default) func SetCookie(ctx echo.Context, key string, value string, args ...interface{}) { + if len(args) == 0 { + args = append(args, ctx.CookieOptions()) + } ctx.SetCookie(key, value, args...) } From 1b04690a969647deb18118c68bb1724ba1698dab Mon Sep 17 00:00:00 2001 From: Hank Shen Date: Mon, 15 Jun 2020 16:35:17 +0800 Subject: [PATCH 17/38] update --- store.go | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/store.go b/store.go index 21934bd..58a8476 100644 --- a/store.go +++ b/store.go @@ -30,8 +30,7 @@ type Store interface { New(ctx echo.Context, name string) (*Session, error) // Save should persist session to the underlying store implementation. - // @param args:maxAge(seconds),path(/),domain,secure,httpOnly,sameSite(lax/strict/default) - Save(ctx echo.Context, s *Session, args ...interface{}) error + Save(ctx echo.Context, s *Session) error } // CookieStore ---------------------------------------------------------------- @@ -96,13 +95,13 @@ func (s *CookieStore) New(ctx echo.Context, name string) (*Session, error) { } // Save adds a single session to the response. -func (s *CookieStore) Save(ctx echo.Context, session *Session, args ...interface{}) error { +func (s *CookieStore) Save(ctx echo.Context, session *Session) error { encoded, err := securecookie.EncodeMulti(session.Name(), session.Values, s.Codecs...) if err != nil { return err } - SetCookie(ctx, session.Name(), encoded, args...) + SetCookie(ctx, session.Name(), encoded) return nil } @@ -190,7 +189,7 @@ func (s *FilesystemStore) New(ctx echo.Context, name string) (*Session, error) { } // Save adds a single session to the response. -func (s *FilesystemStore) Save(ctx echo.Context, session *Session, args ...interface{}) error { +func (s *FilesystemStore) Save(ctx echo.Context, session *Session) error { // Delete if max-age is < 0 if ctx.CookieOptions().MaxAge < 0 { if err := s.erase(session); err != nil { @@ -214,7 +213,7 @@ func (s *FilesystemStore) Save(ctx echo.Context, session *Session, args ...inter if err != nil { return err } - SetCookie(ctx, session.Name(), encoded, args...) + SetCookie(ctx, session.Name(), encoded) return nil } From 5ee2e741c089057300620e8c18cb8b1741c57067 Mon Sep 17 00:00:00 2001 From: Hank Shen Date: Mon, 15 Jun 2020 20:36:28 +0800 Subject: [PATCH 18/38] update --- store.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/store.go b/store.go index 58a8476..fe714f4 100644 --- a/store.go +++ b/store.go @@ -208,6 +208,9 @@ func (s *FilesystemStore) Save(ctx echo.Context, session *Session) error { if err := s.save(session); err != nil { return err } + if !session.IsNew { + return nil + } encoded, err := securecookie.EncodeMulti(session.Name(), session.ID, s.Codecs...) if err != nil { From e7dd49c7c4f582596afa07150f3897c88edb25cb Mon Sep 17 00:00:00 2001 From: Hank Shen Date: Mon, 15 Jun 2020 22:32:29 +0800 Subject: [PATCH 19/38] update --- store.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/store.go b/store.go index fe714f4..58a8476 100644 --- a/store.go +++ b/store.go @@ -208,9 +208,6 @@ func (s *FilesystemStore) Save(ctx echo.Context, session *Session) error { if err := s.save(session); err != nil { return err } - if !session.IsNew { - return nil - } encoded, err := securecookie.EncodeMulti(session.Name(), session.ID, s.Codecs...) if err != nil { From 0b7b4a84d61a773534923232917bbf62cc6597da Mon Sep 17 00:00:00 2001 From: Hank Shen Date: Sun, 22 Nov 2020 17:27:36 +0800 Subject: [PATCH 20/38] update --- store.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/store.go b/store.go index 58a8476..b730903 100644 --- a/store.go +++ b/store.go @@ -28,6 +28,7 @@ type Store interface { // Note that New should never return a nil session, even in the case of // an error if using the Registry infrastructure to cache the session. New(ctx echo.Context, name string) (*Session, error) + Reload(ctx echo.Context, s *Session) error // Save should persist session to the underlying store implementation. Save(ctx echo.Context, s *Session) error @@ -94,6 +95,10 @@ func (s *CookieStore) New(ctx echo.Context, name string) (*Session, error) { return session, err } +func (s *CookieStore) Reload(_ echo.Context, _ *Session) error { + return nil +} + // Save adds a single session to the response. func (s *CookieStore) Save(ctx echo.Context, session *Session) error { encoded, err := securecookie.EncodeMulti(session.Name(), session.Values, @@ -188,6 +193,14 @@ func (s *FilesystemStore) New(ctx echo.Context, name string) (*Session, error) { return session, err } +func (s *FilesystemStore) Reload(ctx echo.Context, session *Session) error { + err := s.load(ctx, session) + if err == nil { + session.IsNew = false + } + return err +} + // Save adds a single session to the response. func (s *FilesystemStore) Save(ctx echo.Context, session *Session) error { // Delete if max-age is < 0 From d1d15b8bee221bb4a393bf2ca565777036b61121 Mon Sep 17 00:00:00 2001 From: Hank Shen Date: Sun, 22 Nov 2020 17:40:53 +0800 Subject: [PATCH 21/38] update --- sessions.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sessions.go b/sessions.go index 2f20258..db4a57b 100644 --- a/sessions.go +++ b/sessions.go @@ -73,6 +73,11 @@ func (s *Session) AddFlash(value interface{}, vars ...string) { s.Values[key] = append(flashes, value) } +// Reload reload session data +func (s *Session) Reload(ctx echo.Context) error { + return s.store.Reload(ctx, s) +} + // Save is a convenience method to save this session. It is the same as calling // store.Save(request, response, session). You should call Save before writing to // the response or returning from the handler. From e83c830d057ab0535d0ba173d9a35a685d62a794 Mon Sep 17 00:00:00 2001 From: Hank Shen Date: Mon, 23 Nov 2020 09:28:43 +0800 Subject: [PATCH 22/38] update --- store.go | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/store.go b/store.go index b730903..a17fda6 100644 --- a/store.go +++ b/store.go @@ -34,6 +34,11 @@ type Store interface { Save(ctx echo.Context, s *Session) error } +// IDGenerator session id generator +type IDGenerator interface { + GenerateID(ctx echo.Context, session *Session) (string, error) +} + // CookieStore ---------------------------------------------------------------- // NewCookieStore returns a new CookieStore. @@ -90,13 +95,29 @@ func (s *CookieStore) New(ctx echo.Context, name string) (*Session, error) { s.Codecs...) if err == nil { session.IsNew = false + session.ID = v } } return session, err } -func (s *CookieStore) Reload(_ echo.Context, _ *Session) error { - return nil +func (s *CookieStore) Reload(ctx echo.Context, session *Session) error { + if len(session.ID) == 0 { + return nil + } + err := securecookie.DecodeMultiWithMaxAge( + session.Name(), session.ID, &session.Values, + ctx.CookieOptions().MaxAge, + s.Codecs...) + if err == nil { + session.IsNew = false + } + return err +} + +func (s *CookieStore) GenerateID(ctx echo.Context, session *Session) (string, error) { + return securecookie.EncodeMulti(session.Name(), session.Values, + s.Codecs...) } // Save adds a single session to the response. From 1f34ca1aac1e31d7e577d3b4aa2c0d96474f6ca0 Mon Sep 17 00:00:00 2001 From: Hank Shen Date: Tue, 15 Dec 2020 16:38:47 +0800 Subject: [PATCH 23/38] update --- store.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/store.go b/store.go index a17fda6..81a350e 100644 --- a/store.go +++ b/store.go @@ -226,7 +226,7 @@ func (s *FilesystemStore) Reload(ctx echo.Context, session *Session) error { func (s *FilesystemStore) Save(ctx echo.Context, session *Session) error { // Delete if max-age is < 0 if ctx.CookieOptions().MaxAge < 0 { - if err := s.erase(session); err != nil { + if err := s.erase(session); err != nil && !os.IsNotExist(err) { return err } SetCookie(ctx, session.Name(), "", -1) From 86db493d73044ebad01ac419dd380f45298bdd35 Mon Sep 17 00:00:00 2001 From: Hank Shen Date: Tue, 18 May 2021 22:43:52 +0800 Subject: [PATCH 24/38] update --- store.go | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/store.go b/store.go index 81a350e..21d004f 100644 --- a/store.go +++ b/store.go @@ -11,6 +11,7 @@ import ( "path/filepath" "strings" "sync" + "time" "github.com/admpub/securecookie" "github.com/webx-top/echo" @@ -154,7 +155,7 @@ var fileMutex sync.RWMutex // // See NewCookieStore() for a description of the other parameters. func NewFilesystemStore(path string, keyPairs ...[]byte) *FilesystemStore { - if path == "" { + if len(path) == 0 { path = os.TempDir() } fs := &FilesystemStore{ @@ -307,3 +308,25 @@ func (s *FilesystemStore) load(ctx echo.Context, session *Session) error { } return nil } + +func (s *FilesystemStore) DeleteExpired(maxAge float64) error { + if maxAge <= 0 { + return nil + } + err := filepath.Walk(s.path, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if info.IsDir() { + return err + } + if !strings.HasPrefix(info.Name(), `session_`) { + return err + } + if time.Since(info.ModTime()).Seconds() > maxAge { + err = os.Remove(path) + } + return err + }) + return err +} From ccf4afe08439ae1d07ee1f32ad69b6b527f8e782 Mon Sep 17 00:00:00 2001 From: Hank Shen Date: Wed, 19 May 2021 11:34:31 +0800 Subject: [PATCH 25/38] update --- store.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/store.go b/store.go index 21d004f..3a008d4 100644 --- a/store.go +++ b/store.go @@ -33,6 +33,8 @@ type Store interface { // Save should persist session to the underlying store implementation. Save(ctx echo.Context, s *Session) error + // Remove server-side data + Remove(sessionID string) error } // IDGenerator session id generator @@ -132,6 +134,10 @@ func (s *CookieStore) Save(ctx echo.Context, session *Session) error { return nil } +func (s *CookieStore) Remove(sessionID string) error { + return nil +} + // MaxAge sets the maximum age for the store and the underlying cookie // implementation. Individual sessions can be deleted by setting Options.MaxAge // = -1 for that session. @@ -252,6 +258,18 @@ func (s *FilesystemStore) Save(ctx echo.Context, session *Session) error { return nil } +func (s *FilesystemStore) Remove(sessionID string) error { + if len(sessionID) == 0 { + return nil + } + filename := filepath.Join(s.path, "session_"+sessionID) + fileMutex.RLock() + defer fileMutex.RUnlock() + + err := os.Remove(filename) + return err +} + // delete session file func (s *FilesystemStore) erase(session *Session) error { if len(session.ID) == 0 { From 146fca184119daae9dd6f7d21ea9cf2b75ddbf7d Mon Sep 17 00:00:00 2001 From: Hank Shen Date: Wed, 19 May 2021 12:57:42 +0800 Subject: [PATCH 26/38] update --- store.go | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/store.go b/store.go index 3a008d4..3d3bf02 100644 --- a/store.go +++ b/store.go @@ -233,7 +233,7 @@ func (s *FilesystemStore) Reload(ctx echo.Context, session *Session) error { func (s *FilesystemStore) Save(ctx echo.Context, session *Session) error { // Delete if max-age is < 0 if ctx.CookieOptions().MaxAge < 0 { - if err := s.erase(session); err != nil && !os.IsNotExist(err) { + if err := s.erase(session); err != nil { return err } SetCookie(ctx, session.Name(), "", -1) @@ -267,20 +267,15 @@ func (s *FilesystemStore) Remove(sessionID string) error { defer fileMutex.RUnlock() err := os.Remove(filename) + if err != nil && os.IsNotExist(err) { + return nil + } return err } // delete session file func (s *FilesystemStore) erase(session *Session) error { - if len(session.ID) == 0 { - return nil - } - filename := filepath.Join(s.path, "session_"+session.ID) - fileMutex.RLock() - defer fileMutex.RUnlock() - - err := os.Remove(filename) - return err + return s.Remove(session.ID) } // MaxAge sets the maximum age for the store and the underlying cookie From 370893cdea2cfbcc42ce82c2d5c942db4d2359dc Mon Sep 17 00:00:00 2001 From: Hank Shen Date: Wed, 27 Oct 2021 11:30:19 +0800 Subject: [PATCH 27/38] update --- sessions.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/sessions.go b/sessions.go index db4a57b..147889e 100644 --- a/sessions.go +++ b/sessions.go @@ -107,12 +107,17 @@ type sessionInfo struct { const registryKey = `webx:mw.sessions` // GetRegistry returns a registry instance for the current request. -func GetRegistry(ctx echo.Context) *Registry { - registry := &Registry{ +func GetRegistry(ctx echo.Context) (registry *Registry) { + actual, loaded := ctx.Internal().Load(registryKey) + if loaded { + registry = actual.(*Registry) + return + } + registry = &Registry{ context: ctx, sessions: make(map[string]sessionInfo), } - actual, loaded := ctx.Internal().LoadOrStore(registryKey, registry) + actual, loaded = ctx.Internal().LoadOrStore(registryKey, registry) if loaded { registry = actual.(*Registry) } From 2a94acab148e3f71c0cf818bfdbe4fe98cd33874 Mon Sep 17 00:00:00 2001 From: Hank Shen Date: Thu, 20 Jan 2022 16:19:49 +0800 Subject: [PATCH 28/38] update --- sessions.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sessions.go b/sessions.go index 147889e..dcddc42 100644 --- a/sessions.go +++ b/sessions.go @@ -139,8 +139,14 @@ func (s *Registry) Get(store Store, name string) (session *Session, err error) { } if info, ok := s.sessions[name]; ok { session, err = info.s, info.e + if err != nil { + return + } } else { session, err = store.New(s.context, name) + if err != nil { + return + } session.name = name s.sessions[name] = sessionInfo{s: session, e: err} } From 514d30dd4689230248087fb9edc543a4d6d61121 Mon Sep 17 00:00:00 2001 From: Hank Shen Date: Wed, 29 Nov 2023 14:54:10 +0800 Subject: [PATCH 29/38] update --- .gitignore | 2 ++ store.go | 5 ++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 598ae79..b958722 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ /.vscode +go.mod +go.sum \ No newline at end of file diff --git a/store.go b/store.go index 3d3bf02..00269cd 100644 --- a/store.go +++ b/store.go @@ -6,7 +6,6 @@ package sessions import ( "encoding/base32" - "io/ioutil" "os" "path/filepath" "strings" @@ -300,7 +299,7 @@ func (s *FilesystemStore) save(session *Session) error { filename := filepath.Join(s.path, "session_"+session.ID) fileMutex.Lock() defer fileMutex.Unlock() - return ioutil.WriteFile(filename, []byte(encoded), 0600) + return os.WriteFile(filename, []byte(encoded), 0600) } // load reads a file and decodes its content into session.Values. @@ -308,7 +307,7 @@ func (s *FilesystemStore) load(ctx echo.Context, session *Session) error { filename := filepath.Join(s.path, "session_"+session.ID) fileMutex.RLock() defer fileMutex.RUnlock() - fdata, err := ioutil.ReadFile(filename) + fdata, err := os.ReadFile(filename) if err != nil { return err } From 838d7bfd956d62a5a266455a874a4c609a9fe56f Mon Sep 17 00:00:00 2001 From: Hank Shen Date: Wed, 6 Dec 2023 12:07:52 +0800 Subject: [PATCH 30/38] update --- store.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/store.go b/store.go index 00269cd..1ce798d 100644 --- a/store.go +++ b/store.go @@ -159,12 +159,12 @@ var fileMutex sync.RWMutex // it will use os.TempDir(). // // See NewCookieStore() for a description of the other parameters. -func NewFilesystemStore(path string, keyPairs ...[]byte) *FilesystemStore { +func NewFilesystemStore(path string) *FilesystemStore { if len(path) == 0 { path = os.TempDir() } fs := &FilesystemStore{ - Codecs: securecookie.CodecsFromPairs(keyPairs...), + Codecs: []securecookie.Codec{securecookie.NewLiteCodec()}, path: path, } return fs From 2e13a9f7101b3b83692b17951d6748e7c827c51c Mon Sep 17 00:00:00 2001 From: Hank Shen Date: Wed, 6 Dec 2023 12:45:23 +0800 Subject: [PATCH 31/38] update --- store.go | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/store.go b/store.go index 1ce798d..ca7b55c 100644 --- a/store.go +++ b/store.go @@ -159,12 +159,12 @@ var fileMutex sync.RWMutex // it will use os.TempDir(). // // See NewCookieStore() for a description of the other parameters. -func NewFilesystemStore(path string) *FilesystemStore { +func NewFilesystemStore(path string, keyPairs ...[]byte) *FilesystemStore { if len(path) == 0 { path = os.TempDir() } fs := &FilesystemStore{ - Codecs: []securecookie.Codec{securecookie.NewLiteCodec()}, + Codecs: securecookie.CodecsFromPairs(keyPairs...), path: path, } return fs @@ -291,15 +291,14 @@ func (s *FilesystemStore) MaxAge(age int) { // save writes encoded session.Values to a file. func (s *FilesystemStore) save(session *Session) error { - encoded, err := securecookie.EncodeMulti(session.Name(), session.Values, - s.Codecs...) + b, err := securecookie.Gob.Serialize(session.Values) if err != nil { return err } filename := filepath.Join(s.path, "session_"+session.ID) fileMutex.Lock() defer fileMutex.Unlock() - return os.WriteFile(filename, []byte(encoded), 0600) + return os.WriteFile(filename, b, 0600) } // load reads a file and decodes its content into session.Values. @@ -311,14 +310,7 @@ func (s *FilesystemStore) load(ctx echo.Context, session *Session) error { if err != nil { return err } - if err = securecookie.DecodeMultiWithMaxAge( - session.Name(), string(fdata), - &session.Values, - ctx.CookieOptions().MaxAge, - s.Codecs...); err != nil { - return err - } - return nil + return securecookie.Gob.Deserialize(fdata, &session.Values) } func (s *FilesystemStore) DeleteExpired(maxAge float64) error { From 793b0a2f7e8eec8429370ad9a957b7127fe376c4 Mon Sep 17 00:00:00 2001 From: Hank Shen Date: Wed, 6 Dec 2023 12:47:28 +0800 Subject: [PATCH 32/38] update --- utils.go | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 utils.go diff --git a/utils.go b/utils.go new file mode 100644 index 0000000..f31e1a8 --- /dev/null +++ b/utils.go @@ -0,0 +1,8 @@ +package sessions + +import "encoding/gob" + +func RegisterGob(v interface{}) { + defer recover() + gob.Register(v) +} From f5794c589174e27ea506be5dd52dc71edf0b2b15 Mon Sep 17 00:00:00 2001 From: Hank Shen Date: Sat, 23 Nov 2024 17:20:53 +0800 Subject: [PATCH 33/38] update --- cookie.go | 23 --- cookie_test.go | 67 -------- go.mod | 43 ++++- go.sum | 349 +++++++++++++++++++++++++++++++++++++++- options.go | 24 --- sessions.go | 16 ++ sessions_values_test.go | 15 ++ store.go | 16 +- 8 files changed, 432 insertions(+), 121 deletions(-) delete mode 100644 cookie.go delete mode 100644 cookie_test.go delete mode 100644 options.go create mode 100644 sessions_values_test.go diff --git a/cookie.go b/cookie.go deleted file mode 100644 index fd6f48c..0000000 --- a/cookie.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Gorilla Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package sessions - -import "net/http" - -// newCookieFromOptions returns an http.Cookie with the options set. -func newCookieFromOptions(name, value string, options *Options) *http.Cookie { - return &http.Cookie{ - Name: name, - Value: value, - Path: options.Path, - Domain: options.Domain, - MaxAge: options.MaxAge, - Secure: options.Secure, - HttpOnly: options.HttpOnly, - Partitioned: options.Partitioned, - SameSite: options.SameSite, - } - -} diff --git a/cookie_test.go b/cookie_test.go deleted file mode 100644 index de530ca..0000000 --- a/cookie_test.go +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2012 The Gorilla Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package sessions - -import ( - "testing" -) - -// Test for creating new http.Cookie from name, value and options -func TestNewCookieFromOptions(t *testing.T) { - tests := []struct { - name string - value string - path string - domain string - maxAge int - secure bool - httpOnly bool - partitioned bool - }{ - {"", "bar", "/foo/bar", "foo.example.com", 3600, true, true, true}, - {"foo", "", "/foo/bar", "foo.example.com", 3600, true, true, true}, - {"foo", "bar", "", "foo.example.com", 3600, true, true, true}, - {"foo", "bar", "/foo/bar", "", 3600, true, true, true}, - {"foo", "bar", "/foo/bar", "foo.example.com", 0, true, true, true}, - {"foo", "bar", "/foo/bar", "foo.example.com", 3600, false, true, true}, - {"foo", "bar", "/foo/bar", "foo.example.com", 3600, true, false, true}, - {"foo", "bar", "/foo/bar", "foo.example.com", 3600, true, true, false}, - } - for i, v := range tests { - options := &Options{ - Path: v.path, - Domain: v.domain, - MaxAge: v.maxAge, - Secure: v.secure, - HttpOnly: v.httpOnly, - Partitioned: v.partitioned, - } - cookie := newCookieFromOptions(v.name, v.value, options) - if cookie.Name != v.name { - t.Fatalf("%v: bad cookie name: got %q, want %q", i+1, cookie.Name, v.name) - } - if cookie.Value != v.value { - t.Fatalf("%v: bad cookie value: got %q, want %q", i+1, cookie.Value, v.value) - } - if cookie.Path != v.path { - t.Fatalf("%v: bad cookie path: got %q, want %q", i+1, cookie.Path, v.path) - } - if cookie.Domain != v.domain { - t.Fatalf("%v: bad cookie domain: got %q, want %q", i+1, cookie.Domain, v.domain) - } - if cookie.MaxAge != v.maxAge { - t.Fatalf("%v: bad cookie maxAge: got %q, want %q", i+1, cookie.MaxAge, v.maxAge) - } - if cookie.Secure != v.secure { - t.Fatalf("%v: bad cookie secure: got %v, want %v", i+1, cookie.Secure, v.secure) - } - if cookie.HttpOnly != v.httpOnly { - t.Fatalf("%v: bad cookie httpOnly: got %v, want %v", i+1, cookie.HttpOnly, v.httpOnly) - } - if cookie.Partitioned != v.partitioned { - t.Fatalf("%v: bad cookie partitioned: got %v, want %v", i+1, cookie.Partitioned, v.partitioned) - } - } -} diff --git a/go.mod b/go.mod index 25a82cc..89eca4f 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,45 @@ module github.com/gorilla/sessions go 1.23 -require github.com/gorilla/securecookie v1.1.2 +require ( + github.com/admpub/securecookie v1.3.0 + github.com/stretchr/testify v1.9.0 + github.com/webx-top/echo v1.13.1 +) + +require ( + github.com/admpub/color v1.8.1 // indirect + github.com/admpub/decimal v1.3.1 // indirect + github.com/admpub/events v1.3.6 // indirect + github.com/admpub/fsnotify v1.7.0 // indirect + github.com/admpub/go-isatty v0.0.11 // indirect + github.com/admpub/go-reuseport v0.0.4 // indirect + github.com/admpub/humanize v0.0.0-20190501023926-5f826e92c8ca // indirect + github.com/admpub/log v1.3.6 // indirect + github.com/admpub/realip v0.2.7 // indirect + github.com/admpub/timeago v1.2.2 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/francoispqt/gojay v1.2.13 // indirect + github.com/goccy/go-json v0.10.3 // indirect + github.com/hashicorp/go-version v1.7.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/webx-top/captcha v0.1.0 // indirect + github.com/webx-top/codec v0.3.0 // indirect + github.com/webx-top/com v1.3.19 // indirect + github.com/webx-top/poolx v0.0.0-20210912044716-5cfa2d58e380 // indirect + github.com/webx-top/tagfast v0.0.1 // indirect + github.com/webx-top/validation v0.0.3 // indirect + golang.org/x/crypto v0.29.0 // indirect + golang.org/x/net v0.31.0 // indirect + golang.org/x/sync v0.9.0 // indirect + golang.org/x/sys v0.27.0 // indirect + golang.org/x/text v0.20.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/go.sum b/go.sum index 285ffee..9d28859 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,348 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo= +dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= +dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= +dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= +dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= +git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/admpub/color v1.8.0/go.mod h1:QS3d/SkJwNQGG0vKWQhtwnwh36JeyqIywgUEqOpXSv8= +github.com/admpub/color v1.8.1 h1:kgx9vC9+KvQ8L1RieP1TZa2qq3lMda+duRKcpZt9BU8= +github.com/admpub/color v1.8.1/go.mod h1:3fk9BXRe+f3UjWSTgVjqUcI4Ei05fLaEPjVajrqMJhY= +github.com/admpub/decimal v1.3.1 h1:+lLbDXQoBb0fxtnMK7r3ZRFFdREV5GIUNculDQ6oSo8= +github.com/admpub/decimal v1.3.1/go.mod h1:QJItPT9L1pPsXkS6fnwWB0FHlSDE7G0x6KOQfgAWyM4= +github.com/admpub/events v1.3.6 h1:sspprUCsMj/mZUPLfs5Ol7xNUvGl2v1QlQnp1U+ouQE= +github.com/admpub/events v1.3.6/go.mod h1:i7MCA/n2a8k/SApXTw+RigSfXO/GKnQQwEty1su24Jc= +github.com/admpub/fsnotify v1.7.0 h1:pI04ANljHE5cS3fr+uXMgDG4/Cv3iye40nH/oZE8pB0= +github.com/admpub/fsnotify v1.7.0/go.mod h1:D9ecq8Ksz5grAhvRRrbN7AdVXnwYx3OxM1+xfjru4+4= +github.com/admpub/go-isatty v0.0.11 h1:jOUJR3gc3eUM4pBaHZoOWqkjr5DGYPGrp3xalspA+5U= +github.com/admpub/go-isatty v0.0.11/go.mod h1:EsPQsKLbNzPWj/avtgWBP509ZqC8PGYw2ZrQKwDCFNs= +github.com/admpub/go-reuseport v0.0.4 h1:6DoWfs/aJAqh7ATd1iJ8hosYWLQXUihlbvNntWQgwhA= +github.com/admpub/go-reuseport v0.0.4/go.mod h1:3iRczQ4CwQFVTUP7RMg5AH2fW/jGEZZuNskUHn72cfQ= +github.com/admpub/humanize v0.0.0-20190501023926-5f826e92c8ca h1:9mfauR3d9p41BFnAoXmHc2z8yHcgg+3+jT1hbnQrtXo= +github.com/admpub/humanize v0.0.0-20190501023926-5f826e92c8ca/go.mod h1:eHL6IsGOvDKqPc9Zp0d0NNayoEYoJ+UC+vj6zG0lGCY= +github.com/admpub/log v1.3.6 h1:fvklF0qsrIjpoAuZPKOBw0V7kbyoVAmHgNuoLtlfcA0= +github.com/admpub/log v1.3.6/go.mod h1:xoQ74l+OC85dML+cPu3uemC/8G/BC2BjIvoxRZ4jT4g= +github.com/admpub/realip v0.2.7 h1:lefF1kpA3liKqq43PzM9D2Ex2imEeix/aMjSmmyMphY= +github.com/admpub/realip v0.2.7/go.mod h1:Ini0GwP0RvSbVLPReALn5zYYRi7Z2wpi2C/7HVX9Ii4= +github.com/admpub/securecookie v1.3.0 h1:SIQfKIwb2vWsIj7m1D1ZJQfKEEKB+I7sJQbTy9k3z1k= +github.com/admpub/securecookie v1.3.0/go.mod h1:KWWRXAWYIUtoK6P7P6vuFXQ8ndFX9v1XgVBfg1zHjf4= +github.com/admpub/timeago v1.2.2 h1:aI47WNHGKNBIWODAnj4lInSPrgqBx2Wh9uHDl/+HBkc= +github.com/admpub/timeago v1.2.2/go.mod h1:5iFnUFGqk2dnVZ2LpOoUserdh2rfTlTfhqB8OIMYZos= +github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= +github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= +github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= +github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= +github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= +github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= +github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= -github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA= -github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= +github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= +github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= +github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= +github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= +github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= +github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= +github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= +github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= +github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= +github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= +github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= +github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw= +github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI= +github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU= +github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag= +github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg= +github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw= +github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y= +github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= +github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q= +github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ= +github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I= +github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0= +github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ= +github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk= +github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4= +github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= +github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= +github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= +github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= +github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= +github.com/webx-top/captcha v0.1.0 h1:uBTGMevM0tlII5Zyj4QbJPI6vTPI0uF+BA4zKLA8avU= +github.com/webx-top/captcha v0.1.0/go.mod h1:E7chb3O5Dqbcta3hBEGRGXGreItjbjPy72ihuqS4+d4= +github.com/webx-top/codec v0.3.0 h1:IQT59k2TMBCVG7XhpEXKgICftk3iJALm5EmeKy1xncI= +github.com/webx-top/codec v0.3.0/go.mod h1:FL2TNTorudSTop040uNCTONOlIJfl6kElJLxyoHHs/g= +github.com/webx-top/com v1.3.19 h1:qaSCEYzHXvzk5RHoW5+gh2g66wIY9uQrTRRbwFt1wlU= +github.com/webx-top/com v1.3.19/go.mod h1:Pw5Yr5UU0ZtwZU0xVyfyRdqf77wyzh+oRNYnOpX9Oyc= +github.com/webx-top/echo v1.13.1 h1:j+l5OI0sxTViO3v6YEvp7x2VX67n0et7DFaPxMo1xU8= +github.com/webx-top/echo v1.13.1/go.mod h1:957lQX6Yqj3e8J4RhXTyRIetvcg5QDXBfRqRtzCqOes= +github.com/webx-top/poolx v0.0.0-20210912044716-5cfa2d58e380 h1:YUDmvTQjrixwGCtlJFm1piLLo7lxMEBnWUqMrlnqyxM= +github.com/webx-top/poolx v0.0.0-20210912044716-5cfa2d58e380/go.mod h1:JGnKm+kSTq2yvbFHttHLvbo2kqY9wZOTXY98YGhZu6Y= +github.com/webx-top/tagfast v0.0.0-20161020041435-9a2065ce3dd2/go.mod h1:pMe3sJitHxbxX2EAI/v9HEAXjodP4c+yUVw3rbKcljI= +github.com/webx-top/tagfast v0.0.1 h1:SNC2ui+ngSCwMaQgtfAsRKFLAt0GuiquMO9jwySfsGU= +github.com/webx-top/tagfast v0.0.1/go.mod h1:vArAB9fuv8AVZ7NfWedERyyY1og7lEHkjuq+o5YuaP8= +github.com/webx-top/validation v0.0.3 h1:6vBoAp5iqjIpfFA+XoCnIzBHcuLjQzxv7MRlshptUqk= +github.com/webx-top/validation v0.0.3/go.mod h1:74lFGn3naxJl8FelK8RfCatVCKDB6G2ckG96tm3w1ug= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= +go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= +golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= +golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= +golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= +golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= +golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210819072135-bce67f096156/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= +golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= +golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= +google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= +sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= diff --git a/options.go b/options.go deleted file mode 100644 index 6ed7934..0000000 --- a/options.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Gorilla Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package sessions - -import "net/http" - -// Options stores configuration for a session or session store. -// -// Fields are a subset of http.Cookie fields. -type Options struct { - Path string - Domain string - // MaxAge=0 means no Max-Age attribute specified and the cookie will be - // deleted after the browser session ends. - // MaxAge<0 means delete cookie immediately. - // MaxAge>0 means Max-Age attribute present and given in seconds. - MaxAge int - Secure bool - HttpOnly bool - Partitioned bool - SameSite http.SameSite -} diff --git a/sessions.go b/sessions.go index dcddc42..d03224f 100644 --- a/sessions.go +++ b/sessions.go @@ -184,6 +184,21 @@ func Save(ctx echo.Context) error { return GetRegistry(ctx).Save(ctx) } +var cookieSameSiteNames = map[string]http.SameSite{ + ``: http.SameSiteDefaultMode, + `lax`: http.SameSiteLaxMode, + `strict`: http.SameSiteStrictMode, + `none`: http.SameSiteNoneMode, +} + +func CookieSameSite(sameSite string) http.SameSite { + v, y := cookieSameSiteNames[sameSite] + if y { + return v + } + return cookieSameSiteNames[``] +} + // NewCookie returns an http.Cookie with the options set. It also sets // the Expires field calculated based on the MaxAge value, for Internet // Explorer compatibility. @@ -196,6 +211,7 @@ func NewCookie(ctx echo.Context, name, value string) *http.Cookie { Domain: options.Domain, MaxAge: options.MaxAge, Secure: options.Secure, + SameSite: CookieSameSite(options.SameSite), HttpOnly: options.HttpOnly, } if options.MaxAge > 0 { diff --git a/sessions_values_test.go b/sessions_values_test.go new file mode 100644 index 0000000..53d78d0 --- /dev/null +++ b/sessions_values_test.go @@ -0,0 +1,15 @@ +package sessions + +import ( + "testing" + + "github.com/admpub/securecookie" + "github.com/stretchr/testify/require" +) + +func TestEmptyValues(t *testing.T) { + b, err := securecookie.Gob.Serialize(map[interface{}]interface{}{`A`: 1}) + require.NoError(t, err) + require.NotEmpty(t, b) + t.Logf(`%v: %d`, b, len(b)) +} diff --git a/store.go b/store.go index df839bd..864f2d2 100644 --- a/store.go +++ b/store.go @@ -213,7 +213,7 @@ func (s *FilesystemStore) New(ctx echo.Context, name string) (*Session, error) { ctx.CookieOptions().MaxAge, s.Codecs...) if err == nil { - err = s.load(ctx, session) + err = s.load(session) if err == nil { session.IsNew = false } @@ -223,7 +223,7 @@ func (s *FilesystemStore) New(ctx echo.Context, name string) (*Session, error) { } func (s *FilesystemStore) Reload(ctx echo.Context, session *Session) error { - err := s.load(ctx, session) + err := s.load(session) if err == nil { session.IsNew = false } @@ -292,6 +292,8 @@ func (s *FilesystemStore) MaxAge(age int) { } } +var emptyGob, _ = securecookie.Gob.Serialize(make(map[interface{}]interface{})) + // save writes encoded session.Values to a file. func (s *FilesystemStore) save(session *Session) error { b, err := securecookie.Gob.Serialize(session.Values) @@ -305,7 +307,7 @@ func (s *FilesystemStore) save(session *Session) error { } // load reads a file and decodes its content into session.Values. -func (s *FilesystemStore) load(ctx echo.Context, session *Session) error { +func (s *FilesystemStore) load(session *Session) error { filename := filepath.Join(s.path, sessionFilePrefix+filepath.Base(session.ID)) fileMutex.RLock() defer fileMutex.RUnlock() @@ -316,10 +318,11 @@ func (s *FilesystemStore) load(ctx echo.Context, session *Session) error { return securecookie.Gob.Deserialize(fdata, &session.Values) } -func (s *FilesystemStore) DeleteExpired(maxAge float64) error { +func (s *FilesystemStore) DeleteExpired(maxAge float64, emptyDataAge float64) error { if maxAge <= 0 { return nil } + emptyLength := int64(len(emptyGob)) err := filepath.Walk(s.path, func(path string, info os.FileInfo, err error) error { if err != nil { return err @@ -332,6 +335,11 @@ func (s *FilesystemStore) DeleteExpired(maxAge float64) error { } if time.Since(info.ModTime()).Seconds() > maxAge { err = os.Remove(path) + return err + } + if emptyDataAge > 0 && emptyLength > 0 && info.Size() == emptyLength && time.Since(info.ModTime()).Seconds() > emptyDataAge { + err = os.Remove(path) + return err } return err }) From 3fb431709ca7df0d7fdbfba5c1ace2fbde66d542 Mon Sep 17 00:00:00 2001 From: Hank Shen Date: Sat, 23 Nov 2024 17:25:17 +0800 Subject: [PATCH 34/38] update --- store.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/store.go b/store.go index 864f2d2..8871b4e 100644 --- a/store.go +++ b/store.go @@ -294,6 +294,10 @@ func (s *FilesystemStore) MaxAge(age int) { var emptyGob, _ = securecookie.Gob.Serialize(make(map[interface{}]interface{})) +func SizeIsEmptyGob(size int64) bool { + return size == int64(len(emptyGob)) +} + // save writes encoded session.Values to a file. func (s *FilesystemStore) save(session *Session) error { b, err := securecookie.Gob.Serialize(session.Values) From e842fee8437fb7aeaa1f44d07d1716a6c7051890 Mon Sep 17 00:00:00 2001 From: Hank Shen Date: Sat, 23 Nov 2024 17:27:56 +0800 Subject: [PATCH 35/38] update --- .gitignore | 1 - go.mod | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 44aa5c0..7c366cb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ /.vscode -go.mod go.sum coverage.coverprofile diff --git a/go.mod b/go.mod index 89eca4f..0aa154b 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/gorilla/sessions +module github.com/admpub/sessions go 1.23 From 27e8eb5f76ea1f505038c23f242c1595b1daf6d7 Mon Sep 17 00:00:00 2001 From: Hank Shen Date: Sat, 23 Nov 2024 17:45:57 +0800 Subject: [PATCH 36/38] update --- store.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/store.go b/store.go index 8871b4e..fd46b54 100644 --- a/store.go +++ b/store.go @@ -295,7 +295,11 @@ func (s *FilesystemStore) MaxAge(age int) { var emptyGob, _ = securecookie.Gob.Serialize(make(map[interface{}]interface{})) func SizeIsEmptyGob(size int64) bool { - return size == int64(len(emptyGob)) + return size == int64(EmptyGobSize()) +} + +func EmptyGobSize() int { + return len(emptyGob) } // save writes encoded session.Values to a file. From 688cbfee5100e757adba4a09e6f941c6f48371bf Mon Sep 17 00:00:00 2001 From: Hank Shen Date: Sat, 22 Feb 2025 21:56:26 +0800 Subject: [PATCH 37/38] update --- .gitignore | 1 + sessions.go | 3 +-- store.go | 63 +++++++++++++++++++++++++++++++++++++--------- store_file_test.go | 47 ++++++++++++++++++++++++++++++++++ 4 files changed, 100 insertions(+), 14 deletions(-) create mode 100644 store_file_test.go diff --git a/.gitignore b/.gitignore index 7c366cb..1e32509 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /.vscode go.sum coverage.coverprofile +testdata diff --git a/sessions.go b/sessions.go index d03224f..7af2963 100644 --- a/sessions.go +++ b/sessions.go @@ -5,7 +5,6 @@ package sessions import ( - "encoding/gob" "fmt" "net/http" "time" @@ -176,7 +175,7 @@ func (s *Registry) Save(ctx echo.Context) error { // Helpers -------------------------------------------------------------------- func init() { - gob.Register([]interface{}{}) + RegisterGob([]interface{}{}) } // Save saves all sessions used during the current request. diff --git a/store.go b/store.go index fd46b54..7171feb 100644 --- a/store.go +++ b/store.go @@ -6,6 +6,7 @@ package sessions import ( "encoding/base32" + "fmt" "os" "path/filepath" "strings" @@ -180,6 +181,7 @@ func NewFilesystemStore(path string, keyPairs ...[]byte) *FilesystemStore { type FilesystemStore struct { Codecs []securecookie.Codec path string + debug bool } // MaxLength restricts the maximum length of new sessions to l. @@ -193,6 +195,10 @@ func (s *FilesystemStore) MaxLength(l int) { } } +func (s *FilesystemStore) SetDebug(on bool) { + s.debug = on +} + // Get returns a session for the given name after adding it to the registry. // // See CookieStore.Get(). @@ -232,6 +238,10 @@ func (s *FilesystemStore) Reload(ctx echo.Context, session *Session) error { var base32RawStdEncoding = base32.StdEncoding.WithPadding(base32.NoPadding) +func makeFileSessionID() string { + return base32RawStdEncoding.EncodeToString(securecookie.GenerateRandomKey(32)) +} + // Save adds a single session to the response. func (s *FilesystemStore) Save(ctx echo.Context, session *Session) error { // Delete if max-age is < 0 @@ -245,8 +255,7 @@ func (s *FilesystemStore) Save(ctx echo.Context, session *Session) error { if len(session.ID) == 0 { // Because the ID is used in the filename, encode it to // use alphanumeric characters only. - session.ID = base32RawStdEncoding.EncodeToString( - securecookie.GenerateRandomKey(32)) + session.ID = makeFileSessionID() } if err := s.save(session); err != nil { return err @@ -264,7 +273,7 @@ func (s *FilesystemStore) Remove(sessionID string) error { if len(sessionID) == 0 { return nil } - filename := filepath.Join(s.path, sessionFilePrefix+filepath.Base(sessionID)) + filename := s.sessionFile(sessionID) fileMutex.RLock() defer fileMutex.RUnlock() @@ -275,6 +284,28 @@ func (s *FilesystemStore) Remove(sessionID string) error { return err } +func (s *FilesystemStore) sessionFile(sessionID string) string { + return filepath.Join(s.path, sessionFilePrefix+filepath.Base(sessionID)) +} + +func (s *FilesystemStore) size(sessionID string) (int64, error) { + if len(sessionID) == 0 { + return 0, nil + } + filename := s.sessionFile(sessionID) + fileMutex.RLock() + defer fileMutex.RUnlock() + + fi, err := os.Stat(filename) + if err != nil { + if os.IsNotExist(err) { + return 0, nil + } + return 0, err + } + return fi.Size(), err +} + // delete session file func (s *FilesystemStore) erase(session *Session) error { return s.Remove(session.ID) @@ -295,11 +326,12 @@ func (s *FilesystemStore) MaxAge(age int) { var emptyGob, _ = securecookie.Gob.Serialize(make(map[interface{}]interface{})) func SizeIsEmptyGob(size int64) bool { - return size == int64(EmptyGobSize()) + return size == EmptyGobSize() } -func EmptyGobSize() int { - return len(emptyGob) +func EmptyGobSize() int64 { + size := len(emptyGob) + return int64(size) } // save writes encoded session.Values to a file. @@ -308,7 +340,7 @@ func (s *FilesystemStore) save(session *Session) error { if err != nil { return err } - filename := filepath.Join(s.path, sessionFilePrefix+filepath.Base(session.ID)) + filename := s.sessionFile(session.ID) fileMutex.Lock() defer fileMutex.Unlock() return os.WriteFile(filename, b, 0600) @@ -316,7 +348,7 @@ func (s *FilesystemStore) save(session *Session) error { // load reads a file and decodes its content into session.Values. func (s *FilesystemStore) load(session *Session) error { - filename := filepath.Join(s.path, sessionFilePrefix+filepath.Base(session.ID)) + filename := s.sessionFile(session.ID) fileMutex.RLock() defer fileMutex.RUnlock() fdata, err := os.ReadFile(filename) @@ -327,10 +359,10 @@ func (s *FilesystemStore) load(session *Session) error { } func (s *FilesystemStore) DeleteExpired(maxAge float64, emptyDataAge float64) error { - if maxAge <= 0 { + if maxAge <= 0 && emptyDataAge <= 0 { return nil } - emptyLength := int64(len(emptyGob)) + emptyLength := EmptyGobSize() err := filepath.Walk(s.path, func(path string, info os.FileInfo, err error) error { if err != nil { return err @@ -341,11 +373,18 @@ func (s *FilesystemStore) DeleteExpired(maxAge float64, emptyDataAge float64) er if !strings.HasPrefix(info.Name(), sessionFilePrefix) { return err } - if time.Since(info.ModTime()).Seconds() > maxAge { + age := time.Since(info.ModTime()).Seconds() + if age > maxAge { + if s.debug { + fmt.Printf("delete %s : {age: %v} > {maxAge: %v}\n", info.Name(), age, maxAge) + } err = os.Remove(path) return err } - if emptyDataAge > 0 && emptyLength > 0 && info.Size() == emptyLength && time.Since(info.ModTime()).Seconds() > emptyDataAge { + if emptyDataAge > 0 && emptyLength > 0 && info.Size() == emptyLength && age > emptyDataAge { + if s.debug { + fmt.Printf("delete %s : {age: %v} > {emptyDataAge: %v}\n", info.Name(), age, emptyDataAge) + } err = os.Remove(path) return err } diff --git a/store_file_test.go b/store_file_test.go new file mode 100644 index 0000000..2627434 --- /dev/null +++ b/store_file_test.go @@ -0,0 +1,47 @@ +package sessions + +import ( + "os" + "testing" + "time" + + "github.com/admpub/securecookie" + "github.com/stretchr/testify/assert" +) + +func TestFileSystemDeleteExpired(t *testing.T) { + sessionDir := `./testdata` + err := os.MkdirAll(sessionDir, os.ModePerm) + assert.NoError(t, err) + st := NewFilesystemStore(sessionDir) + st.debug = true + ss := &Session{ID: makeFileSessionID(), Values: make(map[interface{}]interface{})} + b, err := securecookie.Gob.Serialize(ss.Values) + assert.NoError(t, err) + assert.True(t, SizeIsEmptyGob(int64(len(b)))) + + err = st.save(ss) + assert.NoError(t, err) + size, err := st.size(ss.ID) + assert.NoError(t, err) + assert.True(t, SizeIsEmptyGob(size)) + info, err := os.Stat(st.sessionFile(ss.ID)) + assert.NoError(t, err) + time.Sleep(2 * time.Second) + t.Logf(`lifeTime: %.2f`, time.Since(info.ModTime()).Seconds()) + err = st.DeleteExpired(10, 1) + assert.NoError(t, err) + + ss.Values[`user`] = `user` + err = st.save(ss) + assert.NoError(t, err) + size, err = st.size(ss.ID) + assert.NoError(t, err) + assert.False(t, SizeIsEmptyGob(size)) + t.Logf(`emptyLength: %d; currentLength: %d`, EmptyGobSize(), size) + + time.Sleep(2 * time.Second) + err = st.DeleteExpired(1, 1) + assert.NoError(t, err) + time.Sleep(2 * time.Second) +} From 1bbb2a966ca84813d92de4d00bad0a8ad5bbadf7 Mon Sep 17 00:00:00 2001 From: Hank Shen Date: Sat, 22 Feb 2025 21:58:00 +0800 Subject: [PATCH 38/38] update --- go.mod | 29 ++++++++++++++-------------- go.sum | 61 ++++++++++++++++++++++++---------------------------------- 2 files changed, 40 insertions(+), 50 deletions(-) diff --git a/go.mod b/go.mod index 0aa154b..a8bf1b2 100644 --- a/go.mod +++ b/go.mod @@ -1,11 +1,13 @@ module github.com/admpub/sessions -go 1.23 +go 1.23.0 + +toolchain go1.24.0 require ( github.com/admpub/securecookie v1.3.0 - github.com/stretchr/testify v1.9.0 - github.com/webx-top/echo v1.13.1 + github.com/stretchr/testify v1.10.0 + github.com/webx-top/echo v1.14.5 ) require ( @@ -14,33 +16,32 @@ require ( github.com/admpub/events v1.3.6 // indirect github.com/admpub/fsnotify v1.7.0 // indirect github.com/admpub/go-isatty v0.0.11 // indirect - github.com/admpub/go-reuseport v0.0.4 // indirect + github.com/admpub/go-reuseport v0.5.0 // indirect github.com/admpub/humanize v0.0.0-20190501023926-5f826e92c8ca // indirect - github.com/admpub/log v1.3.6 // indirect + github.com/admpub/log v1.4.0 // indirect github.com/admpub/realip v0.2.7 // indirect github.com/admpub/timeago v1.2.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/francoispqt/gojay v1.2.13 // indirect - github.com/goccy/go-json v0.10.3 // indirect + github.com/goccy/go-json v0.10.5 // indirect github.com/hashicorp/go-version v1.7.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/webx-top/captcha v0.1.0 // indirect github.com/webx-top/codec v0.3.0 // indirect - github.com/webx-top/com v1.3.19 // indirect + github.com/webx-top/com v1.3.25 // indirect github.com/webx-top/poolx v0.0.0-20210912044716-5cfa2d58e380 // indirect github.com/webx-top/tagfast v0.0.1 // indirect github.com/webx-top/validation v0.0.3 // indirect - golang.org/x/crypto v0.29.0 // indirect - golang.org/x/net v0.31.0 // indirect - golang.org/x/sync v0.9.0 // indirect - golang.org/x/sys v0.27.0 // indirect - golang.org/x/text v0.20.0 // indirect + golang.org/x/crypto v0.34.0 // indirect + golang.org/x/net v0.35.0 // indirect + golang.org/x/sync v0.11.0 // indirect + golang.org/x/sys v0.30.0 // indirect + golang.org/x/text v0.22.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 9d28859..a803392 100644 --- a/go.sum +++ b/go.sum @@ -8,7 +8,6 @@ dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1 dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/admpub/color v1.8.0/go.mod h1:QS3d/SkJwNQGG0vKWQhtwnwh36JeyqIywgUEqOpXSv8= github.com/admpub/color v1.8.1 h1:kgx9vC9+KvQ8L1RieP1TZa2qq3lMda+duRKcpZt9BU8= github.com/admpub/color v1.8.1/go.mod h1:3fk9BXRe+f3UjWSTgVjqUcI4Ei05fLaEPjVajrqMJhY= github.com/admpub/decimal v1.3.1 h1:+lLbDXQoBb0fxtnMK7r3ZRFFdREV5GIUNculDQ6oSo8= @@ -19,12 +18,12 @@ github.com/admpub/fsnotify v1.7.0 h1:pI04ANljHE5cS3fr+uXMgDG4/Cv3iye40nH/oZE8pB0 github.com/admpub/fsnotify v1.7.0/go.mod h1:D9ecq8Ksz5grAhvRRrbN7AdVXnwYx3OxM1+xfjru4+4= github.com/admpub/go-isatty v0.0.11 h1:jOUJR3gc3eUM4pBaHZoOWqkjr5DGYPGrp3xalspA+5U= github.com/admpub/go-isatty v0.0.11/go.mod h1:EsPQsKLbNzPWj/avtgWBP509ZqC8PGYw2ZrQKwDCFNs= -github.com/admpub/go-reuseport v0.0.4 h1:6DoWfs/aJAqh7ATd1iJ8hosYWLQXUihlbvNntWQgwhA= -github.com/admpub/go-reuseport v0.0.4/go.mod h1:3iRczQ4CwQFVTUP7RMg5AH2fW/jGEZZuNskUHn72cfQ= +github.com/admpub/go-reuseport v0.5.0 h1:WbIumvnr46Nlq/J1TDHz8QfCk8K//b+AImHf6VBNCow= +github.com/admpub/go-reuseport v0.5.0/go.mod h1:LfaS8MPNO8NNjvGJuEnbOkp7Tec4E0dkxPhBpfgTSx0= github.com/admpub/humanize v0.0.0-20190501023926-5f826e92c8ca h1:9mfauR3d9p41BFnAoXmHc2z8yHcgg+3+jT1hbnQrtXo= github.com/admpub/humanize v0.0.0-20190501023926-5f826e92c8ca/go.mod h1:eHL6IsGOvDKqPc9Zp0d0NNayoEYoJ+UC+vj6zG0lGCY= -github.com/admpub/log v1.3.6 h1:fvklF0qsrIjpoAuZPKOBw0V7kbyoVAmHgNuoLtlfcA0= -github.com/admpub/log v1.3.6/go.mod h1:xoQ74l+OC85dML+cPu3uemC/8G/BC2BjIvoxRZ4jT4g= +github.com/admpub/log v1.4.0 h1:iNar5ZyjMi1ntRUtSIugEaR4pt6DZoNZH/3zw1VbR/Q= +github.com/admpub/log v1.4.0/go.mod h1:bo7BVOu/p+GdOQnv5XhPiPQ60nhLRMhYbAQgKE0gYGw= github.com/admpub/realip v0.2.7 h1:lefF1kpA3liKqq43PzM9D2Ex2imEeix/aMjSmmyMphY= github.com/admpub/realip v0.2.7/go.mod h1:Ini0GwP0RvSbVLPReALn5zYYRi7Z2wpi2C/7HVX9Ii4= github.com/admpub/securecookie v1.3.0 h1:SIQfKIwb2vWsIj7m1D1ZJQfKEEKB+I7sJQbTy9k3z1k= @@ -57,8 +56,8 @@ github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aev github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= -github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= +github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= +github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= @@ -109,12 +108,9 @@ github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= +github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= @@ -146,8 +142,6 @@ github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -190,8 +184,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= @@ -199,10 +193,10 @@ github.com/webx-top/captcha v0.1.0 h1:uBTGMevM0tlII5Zyj4QbJPI6vTPI0uF+BA4zKLA8av github.com/webx-top/captcha v0.1.0/go.mod h1:E7chb3O5Dqbcta3hBEGRGXGreItjbjPy72ihuqS4+d4= github.com/webx-top/codec v0.3.0 h1:IQT59k2TMBCVG7XhpEXKgICftk3iJALm5EmeKy1xncI= github.com/webx-top/codec v0.3.0/go.mod h1:FL2TNTorudSTop040uNCTONOlIJfl6kElJLxyoHHs/g= -github.com/webx-top/com v1.3.19 h1:qaSCEYzHXvzk5RHoW5+gh2g66wIY9uQrTRRbwFt1wlU= -github.com/webx-top/com v1.3.19/go.mod h1:Pw5Yr5UU0ZtwZU0xVyfyRdqf77wyzh+oRNYnOpX9Oyc= -github.com/webx-top/echo v1.13.1 h1:j+l5OI0sxTViO3v6YEvp7x2VX67n0et7DFaPxMo1xU8= -github.com/webx-top/echo v1.13.1/go.mod h1:957lQX6Yqj3e8J4RhXTyRIetvcg5QDXBfRqRtzCqOes= +github.com/webx-top/com v1.3.25 h1:PsQzHem909sao1UWFQqRU0tmijrikfwMGfQRyvWj+3c= +github.com/webx-top/com v1.3.25/go.mod h1:0MjwXQcyy1oXnWqRwabOvvbs+jP82AdR8u0ZB1y64Eg= +github.com/webx-top/echo v1.14.5 h1:HqHH9rPVkVTD5izdDWJ0MSxVUIUpe6YJZdkhVAsOo58= +github.com/webx-top/echo v1.14.5/go.mod h1:y7OwPeGRUzJPxn+zoFOXHoZ+4x7z8LOVSB87ML5fTUA= github.com/webx-top/poolx v0.0.0-20210912044716-5cfa2d58e380 h1:YUDmvTQjrixwGCtlJFm1piLLo7lxMEBnWUqMrlnqyxM= github.com/webx-top/poolx v0.0.0-20210912044716-5cfa2d58e380/go.mod h1:JGnKm+kSTq2yvbFHttHLvbo2kqY9wZOTXY98YGhZu6Y= github.com/webx-top/tagfast v0.0.0-20161020041435-9a2065ce3dd2/go.mod h1:pMe3sJitHxbxX2EAI/v9HEAXjodP4c+yUVw3rbKcljI= @@ -219,8 +213,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= -golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= +golang.org/x/crypto v0.34.0 h1:+/C6tk6rf/+t5DhUketUbD1aNGqiSX3j15Z6xuIDlBA= +golang.org/x/crypto v0.34.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -239,8 +233,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= -golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -252,8 +246,8 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= -golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= +golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -264,30 +258,25 @@ golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210819072135-bce67f096156/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= -golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= -golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=