90 lines
2.2 KiB
Go
90 lines
2.2 KiB
Go
|
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,
|
||
|
})
|
||
|
}
|