package lazysession ¶
import "golazy.dev/lazysession"
Functions ¶
func NewCookie ¶
NewCookie returns an http.Cookie with the options set. It also sets the Expires field calculated based on the MaxAge value, for Internet Explorer compatibility.
func NewCookie(name, value string, options *Options) *http.Cookie
func Save ¶
Save saves all sessions used during the current request.
func Save(r *http.Request, w http.ResponseWriter) error
func WithManager ¶
WithManager stores manager in ctx.
func WithManager(ctx context.Context, manager *Manager) context.Context
Types ¶
type Config ¶
Config describes the default session manager created by lazyapp.
Store is optional. When it is nil, Key and KeyPairs are used to build a CookieStore. Supplying Store keeps the lazyapp integration open to other backends without changing application configuration later.
type Config struct {
Name string
Store Store
// Key is the common app-facing session secret. It is deterministically
// expanded with SHA-256 before constructing the cookie store.
Key string
KeyPairs [][]byte
Options *Options
}
func (c Config) Enabled ¶
Enabled reports whether this config should install session middleware.
func (c Config) Enabled() bool
type CookieStore ¶
CookieStore stores sessions using secure cookies.
type CookieStore struct {
Codecs []lazycookie.Codec
Options *Options // default configuration
}
func NewCookieStore ¶
NewCookieStore returns a new CookieStore.
Keys are defined in pairs to allow key rotation, but the common case is to set a single authentication key and optionally an encryption key.
The first key in a pair is used for authentication and the second for encryption. The encryption key can be set to nil or omitted in the last pair, but the authentication key is required in all pairs.
It is recommended to use an authentication key with 32 or 64 bytes. The encryption key, if set, must be either 16, 24, or 32 bytes to select AES-128, AES-192, or AES-256 modes.
func NewCookieStore(keyPairs ...[]byte) *CookieStore
func (s *CookieStore) Get ¶
Get returns a session for the given name after adding it to the registry.
It returns a new session if the sessions doesn't exist. Access IsNew on the session to check if it is an existing session or a new one.
It returns a new session and an error if the session exists but could not be decoded.
func (s *CookieStore) Get(r *http.Request, name string) (*Session, error)
func (s *CookieStore) MaxAge ¶
MaxAge sets the maximum age for the store and the underlying cookie implementation. Individual sessions can be deleted by setting Options.MaxAge = -1 for that session.
func (s *CookieStore) MaxAge(age int)
func (s *CookieStore) New ¶
New returns a session for the given name without adding it to the registry.
The difference between New() and Get() is that calling New() twice will decode the session data twice, while Get() registers and reuses the same decoded session after the first call.
func (s *CookieStore) New(r *http.Request, name string) (*Session, error)
func (s *CookieStore) Save ¶
Save adds a single session to the response.
func (s *CookieStore) Save(r *http.Request, w http.ResponseWriter,
session *Session) error
type FilesystemStore ¶
FilesystemStore stores sessions in the filesystem.
It also serves as a reference for custom stores.
This store is still experimental and not well tested. Feedback is welcome.
type FilesystemStore struct {
Codecs []lazycookie.Codec
Options *Options // default configuration
// contains filtered or unexported fields
}
func NewFilesystemStore ¶
NewFilesystemStore returns a new FilesystemStore.
The path argument is the directory where sessions will be saved. If empty it will use os.TempDir().
See NewCookieStore() for a description of the other parameters.
func NewFilesystemStore(path string, keyPairs ...[]byte) *FilesystemStore
func (s *FilesystemStore) Get ¶
Get returns a session for the given name after adding it to the registry.
See CookieStore.Get().
func (s *FilesystemStore) Get(r *http.Request, name string) (*Session, error)
func (s *FilesystemStore) MaxAge ¶
MaxAge sets the maximum age for the store and the underlying cookie implementation. Individual sessions can be deleted by setting Options.MaxAge = -1 for that session.
func (s *FilesystemStore) MaxAge(age int)
func (s *FilesystemStore) MaxLength ¶
MaxLength restricts the maximum length of new sessions to l. If l is 0 there is no limit to the size of a session, use with caution. The default for a new FilesystemStore is 4096.
func (s *FilesystemStore) MaxLength(l int)
func (s *FilesystemStore) New ¶
New returns a session for the given name without adding it to the registry.
See CookieStore.New().
func (s *FilesystemStore) New(r *http.Request, name string) (*Session, error)
func (s *FilesystemStore) Save ¶
Save adds a single session to the response.
If the Options.MaxAge of the session is <= 0 then the session file will be deleted from the store path. With this process it enforces the properly session cookie handling so no need to trust in the cookie management in the web browser.
func (s *FilesystemStore) Save(r *http.Request, w http.ResponseWriter,
session *Session) error
type Manager ¶
Manager provides request helpers and middleware for one application session.
type Manager struct {
// contains filtered or unexported fields
}
func ManagerFromContext ¶
ManagerFromContext returns the session manager stored in ctx.
func ManagerFromContext(ctx context.Context) (*Manager, bool)
func NewManager ¶
NewManager creates a request session manager from config.
func NewManager(config Config) (*Manager, error)
func (m *Manager) Get ¶
Get returns the manager's default session for r.
func (m *Manager) Get(r *http.Request) (*Session, error)
func (m *Manager) Handler ¶
Handler installs m into the request context and saves registered sessions before the response is sent.
func (m *Manager) Handler(next http.Handler) http.Handler
func (m *Manager) Name ¶
Name returns the cookie/session name used by this manager.
func (m *Manager) Name() string
func (m *Manager) Store ¶
Store returns the underlying session store.
func (m *Manager) Store() Store
type MultiError ¶
MultiError stores multiple errors.
Borrowed from the App Engine SDK.
type MultiError []error
func (m MultiError) Error ¶
func (m MultiError) Error() string
type Options ¶
Options stores configuration for a session or session store.
Fields are a subset of http.Cookie fields.
type Options struct {
Path string
Domain string
// MaxAge=0 means no Max-Age attribute specified and the cookie will be
// deleted after the browser session ends.
// MaxAge<0 means delete cookie immediately.
// MaxAge>0 means Max-Age attribute present and given in seconds.
MaxAge int
Secure bool
HttpOnly bool
Partitioned bool
SameSite http.SameSite
}
type Registry ¶
Registry stores sessions used during a request.
type Registry struct {
// contains filtered or unexported fields
}
func GetRegistry ¶
GetRegistry returns a registry instance for the current request.
func GetRegistry(r *http.Request) *Registry
func (s *Registry) Get ¶
Get registers and returns a session for the given name and session store.
It returns a new session if there are no sessions registered for the name.
func (s *Registry) Get(store Store, name string) (session *Session, err error)
func (s *Registry) Save ¶
Save saves all sessions registered for the current request.
func (s *Registry) Save(w http.ResponseWriter) error
type Session ¶
Session stores the values and optional configuration for a session.
type Session struct {
// The ID of the session, generated by stores. It should not be used for
// user data.
ID string
// Values contains the user-data for the session.
Values map[interface{}]interface{}
Options *Options
IsNew bool
// contains filtered or unexported fields
}
func Get ¶
Get returns the configured application session from r's context.
func Get(r *http.Request) (*Session, error)
func NewSession ¶
NewSession is called by session stores to create a new session instance.
func NewSession(store Store, name string) *Session
func (s *Session) AddFlash ¶
AddFlash adds a flash message to the session.
A single variadic argument is accepted, and it is optional: it defines the flash key. If not defined "_flash" is used by default.
func (s *Session) AddFlash(value interface{}, vars ...string)
func (s *Session) Flashes ¶
Flashes returns a slice of flash messages from the session.
A single variadic argument is accepted, and it is optional: it defines the flash key. If not defined "_flash" is used by default.
func (s *Session) Flashes(vars ...string) []interface{}
func (s *Session) Name ¶
Name returns the name used to register the session.
func (s *Session) Name() string
func (s *Session) Save ¶
Save is a convenience method to save this session. It is the same as calling store.Save(request, response, session). You should call Save before writing to the response or returning from the handler.
func (s *Session) Save(r *http.Request, w http.ResponseWriter) error
func (s *Session) Store ¶
Store returns the session store used to register the session.
func (s *Session) Store() Store
type Store ¶
Store is an interface for custom session stores.
See CookieStore and FilesystemStore for examples.
type Store interface {
// Get should return a cached session.
Get(r *http.Request, name string) (*Session, error)
// New should create and return a new session.
//
// Note that New should never return a nil session, even in the case of
// an error if using the Registry infrastructure to cache the session.
New(r *http.Request, name string) (*Session, error)
// Save should persist session to the underlying store implementation.
Save(r *http.Request, w http.ResponseWriter, s *Session) error
}
Package lazysession stores per-browser request state in signed cookies or in a custom session store.
A session is a named map of values associated with an HTTP request. Stores load that map from the incoming request and save it to the outgoing response. CookieStore keeps the whole session value inside one authenticated cookie. FilesystemStore keeps only a signed session ID in the cookie and stores the values in files. Application-specific backends can implement Store when the values should live somewhere else, such as a database.
CookieStore and FilesystemStore use lazycookie for signing, decoding, optional encryption, age checks, and key rotation. Authentication means a browser can send a cookie back but cannot alter its value or cookie name without making decode fail. Authentication does not hide the content; pass authentication and block keys as pairs when cookie contents must also be encrypted. The first key pair writes new cookies. Later pairs are read-only fallbacks for old cookies.
The smallest standalone use creates a store, gets a named session, changes Values, and saves before writing the response:
var store = lazysession.NewCookieStore([]byte("32-byte-authentication-secret!!")) func handler(w http.ResponseWriter, r *http.Request) { session, err := store.Get(r, "app_session") if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } session.Values["user_id"] = "42" if err := session.Save(r, w); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } fmt.Fprint(w, "saved") }NewCookieStore expects stable secrets. Generate strong keys with lazycookie.GenerateRandomKey or a secret manager, then persist them in configuration. If a process creates new keys on every startup, existing session cookies cannot be decoded after a restart.
Manager is the GoLazy application layer over Store. A Manager owns the default session name and store for one app. Its Handler installs the manager in the request context, creates the per-request registry, runs the next handler, and saves all sessions registered during the request before the first response write. This is the layer used by lazyapp.
Enable sessions in a GoLazy app through lazyapp.Config.Sessions:
app := lazyapp.New(lazyapp.Config{ Name: "shop", Sessions: lazysession.Config{ Key: os.Getenv("SESSION_KEY"), Options: &lazysession.Options{ Path: "/", MaxAge: 86400 * 30, HttpOnly: true, SameSite: http.SameSiteLaxMode, }, }, })lazyapp calls NewManager, stores the manager in the app context with WithManager, and installs Manager.Handler in the app middleware stack. When the session name is empty, lazyapp derives it from Config.Name and appends "_session"; without lazyapp the package default is "lazy_session". Config.Key is expanded with SHA-256 before the cookie store is created. Use Config.KeyPairs for explicit lazycookie key pairs or Config.Store to provide a custom Store.
Handlers that run under Manager.Handler can use Get to retrieve the configured application session:
func handler(w http.ResponseWriter, r *http.Request) { session, err := lazysession.Get(r) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } session.Values["flash"] = "welcome" }Get reads the Manager from r.Context. ManagerFromContext and WithManager are available for code that builds its own server stack or wants to pass the manager through a base context. Store.Get remains useful when one request needs multiple named sessions or a package intentionally stays independent of the GoLazy app manager.
The request Registry is the reason Save(r, w) can persist every session touched during a request. Store.Get registers the decoded session by name; Save walks that registry and calls the matching Store.Save for each session. Manager.Handler does this automatically. If a handler uses stores directly without the manager, call Session.Save for one session or Save(r, w) for all registered sessions before writing the response.
Flash messages are values that last until read. AddFlash stores a value under the default "_flash" key, or under a custom key when one is passed. Flashes returns the stored values and removes them from the session, which makes them useful for messages shown after a redirect.
Session values are encoded with encoding/gob by default. Basic values work without setup. Custom values stored through interface slots, including flash values, may need gob.Register during program initialization:
type Notice struct { Kind string Text string } func init() { gob.Register(Notice{}) }Options are copied from the store to each new session. Changing store.Options affects future sessions; changing session.Options affects only that response. MaxAge follows http.Cookie semantics: zero omits Max-Age and expires at browser shutdown, a negative value deletes the cookie immediately, and a positive value sets a lifetime in seconds.