From c261597b9adb827bfa16de8f21ce47ac63bec138 Mon Sep 17 00:00:00 2001 From: Alexander NeonXP Kiryukhin Date: Mon, 29 Jul 2024 02:46:54 +0300 Subject: Сессии в отдельном подпакете MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- middleware/context.go | 8 ++-- middleware/session.go | 89 ---------------------------------------- middleware/session/bbolt.go | 2 +- middleware/session/session.go | 94 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 99 insertions(+), 94 deletions(-) delete mode 100644 middleware/session.go create mode 100644 middleware/session/session.go (limited to 'middleware') diff --git a/middleware/context.go b/middleware/context.go index b9ad45f..a76bca0 100644 --- a/middleware/context.go +++ b/middleware/context.go @@ -4,8 +4,8 @@ type ctxKey int const ( requestIDKey ctxKey = iota - sessionIDKey - sessionValueKey - sessionConfigKey - sessionStorerKey + SessionIDKey + SessionValueKey + SessionConfigKey + SessionStorerKey ) diff --git a/middleware/session.go b/middleware/session.go deleted file mode 100644 index 838e088..0000000 --- a/middleware/session.go +++ /dev/null @@ -1,89 +0,0 @@ -package middleware - -import ( - "context" - "errors" - "net/http" - - "go.neonxp.ru/mux" - "go.neonxp.ru/mux/middleware/session" - "go.neonxp.ru/objectid" -) - -type SessionConfig struct { - SessionCookie string - Path string - Domain string - Secure bool - HttpOnly bool - MaxAge int -} - -var DefaultSessionConfig SessionConfig = SessionConfig{ - SessionCookie: "_session", - Path: "/", - Domain: "", - Secure: false, - HttpOnly: true, - MaxAge: 30 * 3600, -} - -func Session(config SessionConfig, storer session.Store) mux.Middleware { - return func(h http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - var ( - sessionID string - values session.Value - ) - cookie, err := r.Cookie(config.SessionCookie) - switch { - case err == nil: - sessionID = cookie.Value - values = storer.Load(r.Context(), sessionID) - case errors.Is(err, http.ErrNoCookie): - sessionID = objectid.New().String() - values = session.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(), sessionValueKey, &values) - ctx = context.WithValue(ctx, sessionIDKey, sessionID) - ctx = context.WithValue(ctx, sessionConfigKey, config) - ctx = context.WithValue(ctx, sessionStorerKey, storer) - - h.ServeHTTP(w, r.WithContext(ctx)) - - storer.Save(r.Context(), sessionID, values) - - }) - } -} - -func SessionFromRequest(r *http.Request) *session.Value { - return r.Context().Value(sessionValueKey).(*session.Value) -} - -func ClearSession(w http.ResponseWriter, r *http.Request) { - storer := r.Context().Value(sessionStorerKey).(session.Store) - sessionID := r.Context().Value(sessionIDKey).(string) - storer.Remove(r.Context(), sessionID) - config := r.Context().Value(sessionConfigKey).(SessionConfig) - http.SetCookie(w, &http.Cookie{ - Name: config.SessionCookie, - Value: sessionID, - Path: config.Path, - Domain: config.Domain, - Secure: config.Secure, - HttpOnly: config.HttpOnly, - MaxAge: -1, - }) -} diff --git a/middleware/session/bbolt.go b/middleware/session/bbolt.go index 1068ed8..be484d7 100644 --- a/middleware/session/bbolt.go +++ b/middleware/session/bbolt.go @@ -9,7 +9,7 @@ import ( "go.etcd.io/bbolt" ) -func New(db *bbolt.DB, bucketName []byte) Store { +func NewBoltStore(db *bbolt.DB, bucketName []byte) Store { return &BoltStore{ db: db, bucketName: bucketName, diff --git a/middleware/session/session.go b/middleware/session/session.go new file mode 100644 index 0000000..4d02bf1 --- /dev/null +++ b/middleware/session/session.go @@ -0,0 +1,94 @@ +package session + +import ( + "context" + "errors" + "net/http" + "sync" + + "go.neonxp.ru/mux" + "go.neonxp.ru/mux/middleware" + "go.neonxp.ru/objectid" +) + +type Config struct { + SessionCookie string + Path string + Domain string + Secure bool + HttpOnly bool + MaxAge int +} + +var DefaultConfig Config = Config{ + SessionCookie: "_session", + Path: "/", + Domain: "", + Secure: false, + HttpOnly: true, + MaxAge: 30 * 3600, +} + +func Middleware(config Config, storer Store) mux.Middleware { + if storer == nil { + storer = &MemoryStore{store: sync.Map{}} + } + + return func(h http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var ( + sessionID string + values Value + ) + cookie, err := r.Cookie(config.SessionCookie) + switch { + case err == nil: + sessionID = cookie.Value + values = storer.Load(r.Context(), 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) + + 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 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) + http.SetCookie(w, &http.Cookie{ + Name: config.SessionCookie, + Value: sessionID, + Path: config.Path, + Domain: config.Domain, + Secure: config.Secure, + HttpOnly: config.HttpOnly, + MaxAge: -1, + }) +} -- cgit v1.2.3