summaryrefslogtreecommitdiff
path: root/middleware/session/session.go
diff options
context:
space:
mode:
Diffstat (limited to 'middleware/session/session.go')
-rw-r--r--middleware/session/session.go94
1 files changed, 94 insertions, 0 deletions
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,
+ })
+}