Sessions
The session package wraps gorilla/sessions to provide server-side HTTP session management. It supports two backing stores out of the box — cookie-based (all data signed into the browser cookie) and filesystem-based (data on disk, only the session ID in the cookie) — and exposes simple get/set/destroy helpers on top of the gorilla *sessions.Session object.
Import
import "github.com/gofastadev/gofasta/pkg/session"Key Types
Store
Store is the package’s main type — a thin wrapper around gorilla/sessions.Store that remembers the session name and exposes convenience methods for reading and writing values.
type Store struct { /* unexported fields */ }SessionConfig (from pkg/config)
The session configuration lives on config.AppConfig and is loaded from config.yaml or the GOFASTA_SESSION_* environment variables.
type SessionConfig struct {
Driver string `koanf:"driver"` // "cookie" or "filesystem"
Secret string `koanf:"secret"` // 32 or 64 bytes for HMAC signing
SessionName string `koanf:"session_name"` // cookie name
FilesystemPath string `koanf:"filesystem_path"` // required when driver=filesystem
}Key Functions
| Function | Signature | Description |
|---|---|---|
NewCookieStore | func NewCookieStore(secret, sessionName string) *Store | Creates a cookie-based session store. All session data is serialized into the browser cookie, signed with secret via HMAC. |
NewFilesystemStore | func NewFilesystemStore(path, secret, sessionName string) *Store | Creates a filesystem-based session store. Only the session ID is stored in the cookie; the actual values live on disk under path. |
Store Methods
| Method | Signature | Description |
|---|---|---|
Get | func (s *Store) Get(r *http.Request) (*sessions.Session, error) | Returns the gorilla *sessions.Session for the current request. |
Save | func (s *Store) Save(r *http.Request, w http.ResponseWriter, session *sessions.Session) error | Persists the session to the response (writes the Set-Cookie header and/or flushes the filesystem file). |
SetValue | func (s *Store) SetValue(r *http.Request, w http.ResponseWriter, key string, value interface{}) error | Convenience helper: fetches the session, writes one key, saves. |
GetValue | func (s *Store) GetValue(r *http.Request, key string) (interface{}, error) | Convenience helper: fetches the session and returns the value under key. |
Destroy | func (s *Store) Destroy(r *http.Request, w http.ResponseWriter) error | Marks the session for deletion by setting MaxAge = -1 and saving. |
Usage
Creating a Store
Choose one of the two constructors. Both return a *Store you can use from any handler.
import "github.com/gofastadev/gofasta/pkg/session"
// Cookie store — simplest, all data lives in the signed cookie.
store := session.NewCookieStore(
"change-me-in-production-32bytes!",
"app_session",
)
// Filesystem store — cookie carries only the ID, data lives on disk.
store := session.NewFilesystemStore(
"./sessions",
"change-me-in-production-32bytes!",
"app_session",
)Writing Values on Login
func (c *AuthController) Login(w http.ResponseWriter, r *http.Request) error {
// ...authenticate the user first...
if err := c.store.SetValue(r, w, "user_id", user.ID.String()); err != nil {
return apperrors.NewInternal("failed to save session", err)
}
if err := c.store.SetValue(r, w, "role", user.Role); err != nil {
return apperrors.NewInternal("failed to save session", err)
}
return httputil.OK(w, map[string]string{"status": "logged in"})
}Reading Values on a Protected Route
func (c *AuthController) Profile(w http.ResponseWriter, r *http.Request) error {
userID, err := c.store.GetValue(r, "user_id")
if err != nil || userID == nil {
return apperrors.NewUnauthorized("not logged in", nil)
}
user, err := c.service.FindByID(r.Context(), userID.(string))
if err != nil {
return err
}
return httputil.OK(w, user)
}Writing Multiple Values in One Save
For efficiency, fetch the underlying *sessions.Session once, mutate its Values map, then save it manually.
sess, err := c.store.Get(r)
if err != nil {
return err
}
sess.Values["user_id"] = user.ID.String()
sess.Values["email"] = user.Email
sess.Values["role"] = user.Role
if err := c.store.Save(r, w, sess); err != nil {
return err
}Logout and Session Destruction
func (c *AuthController) Logout(w http.ResponseWriter, r *http.Request) error {
if err := c.store.Destroy(r, w); err != nil {
return apperrors.NewInternal("failed to destroy session", err)
}
return httputil.OK(w, map[string]string{"status": "logged out"})
}Building the Store from Config
Load SessionConfig from config.AppConfig and branch on the driver:
func buildStore(cfg config.SessionConfig) *session.Store {
switch cfg.Driver {
case "filesystem":
return session.NewFilesystemStore(cfg.FilesystemPath, cfg.Secret, cfg.SessionName)
default:
return session.NewCookieStore(cfg.Secret, cfg.SessionName)
}
}Configuration
Add a session: block to your config.yaml:
session:
driver: cookie # "cookie" or "filesystem"
secret: "change-me-in-production-32bytes!"
session_name: app_session
filesystem_path: "./sessions" # only used when driver=filesystemAny field can be overridden via environment variables with the GOFASTA_ prefix:
export GOFASTA_SESSION_DRIVER=filesystem
export GOFASTA_SESSION_SECRET="my-secure-secret-32bytes!"
export GOFASTA_SESSION_FILESYSTEM_PATH="/var/lib/myapp/sessions"The pkg/config package’s LoadConfig() populates these fields automatically and provides sane defaults (driver: cookie, session_name: app_session, filesystem_path: ./sessions) when they are missing.
Sessions vs JWT
The session and auth packages cover two different authentication styles:
| Concern | Sessions (session) | JWT (auth) |
|---|---|---|
| State | Server-side (cookie or filesystem) | Stateless — the token is self-contained |
| Invalidation | Destroy the server-side entry | Rotate the signing key or maintain a denylist |
| Cross-origin / mobile | Harder — cookies are domain-scoped | Easy — clients send Authorization: Bearer … |
| Best for | Server-rendered web apps on one domain | REST / GraphQL APIs consumed by SPAs or mobile |
A gofasta project can use either, or both, depending on the surface area of the API.
Related Pages
- Auth — JWT-based authentication for stateless APIs
- Config — where
SessionConfiglives - Middleware — wrap your router with logging, CORS, etc.