2024-07-29 02:46:54 +03:00
|
|
|
package session
|
2024-07-29 02:38:17 +03:00
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"errors"
|
|
|
|
"net/http"
|
2024-07-29 02:46:54 +03:00
|
|
|
"sync"
|
2024-07-29 02:38:17 +03:00
|
|
|
|
|
|
|
"go.neonxp.ru/mux"
|
2024-07-29 02:46:54 +03:00
|
|
|
"go.neonxp.ru/mux/middleware"
|
2024-07-29 02:38:17 +03:00
|
|
|
"go.neonxp.ru/objectid"
|
|
|
|
)
|
|
|
|
|
2024-07-29 02:46:54 +03:00
|
|
|
type Config struct {
|
2024-07-29 02:38:17 +03:00
|
|
|
SessionCookie string
|
|
|
|
Path string
|
|
|
|
Domain string
|
|
|
|
Secure bool
|
|
|
|
HttpOnly bool
|
|
|
|
MaxAge int
|
|
|
|
}
|
|
|
|
|
2024-07-29 02:46:54 +03:00
|
|
|
var DefaultConfig Config = Config{
|
2024-07-29 02:38:17 +03:00
|
|
|
SessionCookie: "_session",
|
|
|
|
Path: "/",
|
|
|
|
Domain: "",
|
|
|
|
Secure: false,
|
|
|
|
HttpOnly: true,
|
|
|
|
MaxAge: 30 * 3600,
|
|
|
|
}
|
|
|
|
|
2024-07-29 02:46:54 +03:00
|
|
|
func Middleware(config Config, storer Store) mux.Middleware {
|
|
|
|
if storer == nil {
|
|
|
|
storer = &MemoryStore{store: sync.Map{}}
|
|
|
|
}
|
|
|
|
|
2024-07-29 02:38:17 +03:00
|
|
|
return func(h http.Handler) http.Handler {
|
|
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
var (
|
|
|
|
sessionID string
|
2024-07-29 02:46:54 +03:00
|
|
|
values Value
|
2024-07-29 02:38:17 +03:00
|
|
|
)
|
|
|
|
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()
|
2024-07-29 02:46:54 +03:00
|
|
|
values = Value{}
|
2024-07-29 02:38:17 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
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,
|
|
|
|
})
|
|
|
|
|
2024-07-29 02:46:54 +03:00
|
|
|
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)
|
2024-07-29 02:38:17 +03:00
|
|
|
|
|
|
|
h.ServeHTTP(w, r.WithContext(ctx))
|
|
|
|
|
|
|
|
storer.Save(r.Context(), sessionID, values)
|
|
|
|
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-29 02:46:54 +03:00
|
|
|
func FromRequest(r *http.Request) *Value {
|
|
|
|
return r.Context().Value(middleware.SessionValueKey).(*Value)
|
2024-07-29 02:38:17 +03:00
|
|
|
}
|
|
|
|
|
2024-07-29 02:46:54 +03:00
|
|
|
func Clear(w http.ResponseWriter, r *http.Request) {
|
|
|
|
storer := r.Context().Value(middleware.SessionStorerKey).(Store)
|
|
|
|
sessionID := r.Context().Value(middleware.SessionIDKey).(string)
|
2024-07-29 02:38:17 +03:00
|
|
|
storer.Remove(r.Context(), sessionID)
|
2024-07-29 02:46:54 +03:00
|
|
|
config := r.Context().Value(middleware.SessionConfigKey).(Config)
|
2024-07-29 02:38:17 +03:00
|
|
|
http.SetCookie(w, &http.Cookie{
|
|
|
|
Name: config.SessionCookie,
|
|
|
|
Value: sessionID,
|
|
|
|
Path: config.Path,
|
|
|
|
Domain: config.Domain,
|
|
|
|
Secure: config.Secure,
|
|
|
|
HttpOnly: config.HttpOnly,
|
|
|
|
MaxAge: -1,
|
|
|
|
})
|
|
|
|
}
|