summaryrefslogtreecommitdiff
path: root/middleware/session/session.go
diff options
context:
space:
mode:
authorAlexander NeonXP Kiryukhin <i@neonxp.ru>2024-07-30 00:45:25 +0300
committerAlexander NeonXP Kiryukhin <i@neonxp.ru>2024-07-30 00:45:25 +0300
commit623eaf165a4f248681acfec094f2f1ac1e0ff89f (patch)
tree54a7b7c0be2002b4d9c4d59081e0e9c2bb84628b /middleware/session/session.go
parentc261597b9adb827bfa16de8f21ce47ac63bec138 (diff)
Пересмотрел механизм сессий
Diffstat (limited to 'middleware/session/session.go')
-rw-r--r--middleware/session/session.go114
1 files changed, 74 insertions, 40 deletions
diff --git a/middleware/session/session.go b/middleware/session/session.go
index 4d02bf1..47fc0fb 100644
--- a/middleware/session/session.go
+++ b/middleware/session/session.go
@@ -4,10 +4,9 @@ import (
"context"
"errors"
"net/http"
- "sync"
+ "time"
"go.neonxp.ru/mux"
- "go.neonxp.ru/mux/middleware"
"go.neonxp.ru/objectid"
)
@@ -17,7 +16,7 @@ type Config struct {
Domain string
Secure bool
HttpOnly bool
- MaxAge int
+ MaxAge time.Duration
}
var DefaultConfig Config = Config{
@@ -26,69 +25,104 @@ var DefaultConfig Config = Config{
Domain: "",
Secure: false,
HttpOnly: true,
- MaxAge: 30 * 3600,
+ MaxAge: 365 * 24 * time.Hour,
}
-func Middleware(config Config, storer Store) mux.Middleware {
- if storer == nil {
- storer = &MemoryStore{store: sync.Map{}}
+var (
+ ErrSessionNotFound = errors.New("session not found")
+ ErrNoSessionInContext = errors.New("no session in context")
+)
+
+type SessionManager struct {
+ config *Config
+ storer Store
+}
+
+func New(storer Store) *SessionManager {
+ return NewWithConfig(&DefaultConfig, storer)
+}
+
+func NewWithConfig(config *Config, storer Store) *SessionManager {
+ return &SessionManager{
+ config: config,
+ storer: storer,
}
+}
+func (s *SessionManager) Middleware() mux.Middleware {
return func(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var (
sessionID string
- values Value
+ values Values
)
- cookie, err := r.Cookie(config.SessionCookie)
+ cookie, err := r.Cookie(s.config.SessionCookie)
switch {
case err == nil:
sessionID = cookie.Value
- values = storer.Load(r.Context(), sessionID)
+ values = s.storer.Load(sessionID)
case errors.Is(err, http.ErrNoCookie):
sessionID = objectid.New().String()
- values = Value{}
}
- http.SetCookie(w, &http.Cookie{
- Name: config.SessionCookie,
- Value: sessionID,
- Path: config.Path,
- Domain: config.Domain,
- Secure: config.Secure,
- HttpOnly: config.HttpOnly,
- MaxAge: config.MaxAge,
- })
-
- ctx := context.WithValue(r.Context(), middleware.SessionValueKey, &values)
- ctx = context.WithValue(ctx, middleware.SessionIDKey, sessionID)
- ctx = context.WithValue(ctx, middleware.SessionConfigKey, config)
- ctx = context.WithValue(ctx, middleware.SessionStorerKey, storer)
+ ctx := context.WithValue(r.Context(), sessionManagerKey, s)
+ ctx = context.WithValue(ctx, sessionIDKey, sessionID)
+ ctx = context.WithValue(ctx, sessionValueKey, values)
h.ServeHTTP(w, r.WithContext(ctx))
-
- storer.Save(r.Context(), sessionID, values)
-
})
}
}
-func FromRequest(r *http.Request) *Value {
- return r.Context().Value(middleware.SessionValueKey).(*Value)
+func (s *SessionManager) Values(ctx context.Context) Values {
+ aValue := ctx.Value(sessionValueKey)
+ values, ok := aValue.(Values)
+ if !ok || values == nil {
+ values = Values{}
+ }
+
+ return values
}
-func Clear(w http.ResponseWriter, r *http.Request) {
- storer := r.Context().Value(middleware.SessionStorerKey).(Store)
- sessionID := r.Context().Value(middleware.SessionIDKey).(string)
- storer.Remove(r.Context(), sessionID)
- config := r.Context().Value(middleware.SessionConfigKey).(Config)
+func (s *SessionManager) Save(w http.ResponseWriter, r *http.Request, values Values) error {
+ aSessionID := r.Context().Value(sessionIDKey)
+ sessionID, ok := aSessionID.(string)
+ if !ok {
+ return ErrNoSessionInContext
+ }
+
http.SetCookie(w, &http.Cookie{
- Name: config.SessionCookie,
+ Name: s.config.SessionCookie,
Value: sessionID,
- Path: config.Path,
- Domain: config.Domain,
- Secure: config.Secure,
- HttpOnly: config.HttpOnly,
+ Path: s.config.Path,
+ Domain: s.config.Domain,
+ Secure: s.config.Secure,
+ HttpOnly: s.config.HttpOnly,
+ MaxAge: int(s.config.MaxAge.Seconds()),
+ })
+
+ return s.storer.Save(sessionID, values)
+}
+func (s *SessionManager) Clear(w http.ResponseWriter, r *http.Request) error {
+ aSessionID := r.Context().Value(sessionIDKey)
+ sessionID, ok := aSessionID.(string)
+ if !ok {
+ return ErrNoSessionInContext
+ }
+
+ http.SetCookie(w, &http.Cookie{
+ Name: s.config.SessionCookie,
+ Value: sessionID,
+ Path: s.config.Path,
+ Domain: s.config.Domain,
+ Secure: s.config.Secure,
+ HttpOnly: s.config.HttpOnly,
MaxAge: -1,
})
+
+ return s.storer.Remove(sessionID)
+}
+
+func FromRequest(r *http.Request) *SessionManager {
+ return r.Context().Value(sessionManagerKey).(*SessionManager)
}