mirror of https://github.com/gofiber/fiber.git
189 lines
4.8 KiB
Go
189 lines
4.8 KiB
Go
package session
|
|
|
|
import (
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/gofiber/fiber/v3"
|
|
"github.com/gofiber/fiber/v3/log"
|
|
"github.com/gofiber/utils/v2"
|
|
)
|
|
|
|
// Config defines the configuration for the session middleware.
|
|
type Config struct {
|
|
// Storage interface for storing session data.
|
|
//
|
|
// Optional. Default: memory.New()
|
|
Storage fiber.Storage
|
|
|
|
// Next defines a function to skip this middleware when it returns true.
|
|
// Optional. Default: nil
|
|
Next func(c fiber.Ctx) bool
|
|
|
|
// Store defines the session store.
|
|
//
|
|
// Required.
|
|
Store *Store
|
|
|
|
// ErrorHandler defines a function to handle errors.
|
|
//
|
|
// Optional. Default: nil
|
|
ErrorHandler func(fiber.Ctx, error)
|
|
|
|
// KeyGenerator generates the session key.
|
|
//
|
|
// Optional. Default: utils.UUIDv4
|
|
KeyGenerator func() string
|
|
|
|
// KeyLookup is a string in the format "<source>:<name>" used to extract the session ID from the request.
|
|
//
|
|
// Possible values: "header:<name>", "query:<name>", "cookie:<name>"
|
|
//
|
|
// Optional. Default: "cookie:session_id"
|
|
KeyLookup string
|
|
|
|
// CookieDomain defines the domain of the session cookie.
|
|
//
|
|
// Optional. Default: ""
|
|
CookieDomain string
|
|
|
|
// CookiePath defines the path of the session cookie.
|
|
//
|
|
// Optional. Default: ""
|
|
CookiePath string
|
|
|
|
// CookieSameSite specifies the SameSite attribute of the cookie.
|
|
//
|
|
// Optional. Default: "Lax"
|
|
CookieSameSite string
|
|
|
|
// Source defines where to obtain the session ID.
|
|
source Source
|
|
|
|
// sessionName is the name of the session.
|
|
sessionName string
|
|
|
|
// IdleTimeout defines the maximum duration of inactivity before the session expires.
|
|
//
|
|
// Note: The idle timeout is updated on each `Save()` call. If a middleware handler is used, `Save()` is called automatically.
|
|
//
|
|
// Optional. Default: 30 * time.Minute
|
|
IdleTimeout time.Duration
|
|
|
|
// AbsoluteTimeout defines the maximum duration of the session before it expires.
|
|
//
|
|
// If set to 0, the session will not have an absolute timeout, and will expire after the idle timeout.
|
|
//
|
|
// Optional. Default: 0
|
|
AbsoluteTimeout time.Duration
|
|
|
|
// CookieSecure specifies if the session cookie should be secure.
|
|
//
|
|
// Optional. Default: false
|
|
CookieSecure bool
|
|
|
|
// CookieHTTPOnly specifies if the session cookie should be HTTP-only.
|
|
//
|
|
// Optional. Default: false
|
|
CookieHTTPOnly bool
|
|
|
|
// CookieSessionOnly determines if the cookie should expire when the browser session ends.
|
|
//
|
|
// If true, the cookie will be deleted when the browser is closed.
|
|
// Note: This will not delete the session data from the store.
|
|
//
|
|
// Optional. Default: false
|
|
CookieSessionOnly bool
|
|
}
|
|
|
|
// Source represents the type of session ID source.
|
|
type Source string
|
|
|
|
const (
|
|
SourceCookie Source = "cookie"
|
|
SourceHeader Source = "header"
|
|
SourceURLQuery Source = "query"
|
|
)
|
|
|
|
// ConfigDefault provides the default configuration.
|
|
var ConfigDefault = Config{
|
|
IdleTimeout: 30 * time.Minute,
|
|
KeyLookup: "cookie:session_id",
|
|
KeyGenerator: utils.UUIDv4,
|
|
source: SourceCookie,
|
|
sessionName: "session_id",
|
|
}
|
|
|
|
// DefaultErrorHandler logs the error and sends a 500 status code.
|
|
//
|
|
// Parameters:
|
|
// - c: The Fiber context.
|
|
// - err: The error to handle.
|
|
//
|
|
// Usage:
|
|
//
|
|
// DefaultErrorHandler(c, err)
|
|
func DefaultErrorHandler(c fiber.Ctx, err error) {
|
|
log.Errorf("session: %v", err)
|
|
if sendErr := c.SendStatus(fiber.StatusInternalServerError); sendErr != nil {
|
|
log.Errorf("session: %v", sendErr)
|
|
}
|
|
}
|
|
|
|
// configDefault sets default values for the Config struct.
|
|
//
|
|
// Parameters:
|
|
// - config: Variadic parameter to override the default config.
|
|
//
|
|
// Returns:
|
|
// - Config: The configuration with default values set.
|
|
//
|
|
// Usage:
|
|
//
|
|
// cfg := configDefault()
|
|
// cfg := configDefault(customConfig)
|
|
func configDefault(config ...Config) Config {
|
|
// Return default config if none provided.
|
|
if len(config) < 1 {
|
|
return ConfigDefault
|
|
}
|
|
|
|
// Override default config with provided config.
|
|
cfg := config[0]
|
|
|
|
// Set default values where necessary.
|
|
if cfg.IdleTimeout <= 0 {
|
|
cfg.IdleTimeout = ConfigDefault.IdleTimeout
|
|
}
|
|
// Ensure AbsoluteTimeout is greater than or equal to IdleTimeout.
|
|
if cfg.AbsoluteTimeout > 0 && cfg.AbsoluteTimeout < cfg.IdleTimeout {
|
|
panic("[session] AbsoluteTimeout must be greater than or equal to IdleTimeout")
|
|
}
|
|
if cfg.KeyLookup == "" {
|
|
cfg.KeyLookup = ConfigDefault.KeyLookup
|
|
}
|
|
if cfg.KeyGenerator == nil {
|
|
cfg.KeyGenerator = ConfigDefault.KeyGenerator
|
|
}
|
|
|
|
// Parse KeyLookup into source and session name.
|
|
selectors := strings.Split(cfg.KeyLookup, ":")
|
|
const numSelectors = 2
|
|
if len(selectors) != numSelectors {
|
|
panic("[session] KeyLookup must be in the format '<source>:<name>'")
|
|
}
|
|
switch Source(selectors[0]) {
|
|
case SourceCookie:
|
|
cfg.source = SourceCookie
|
|
case SourceHeader:
|
|
cfg.source = SourceHeader
|
|
case SourceURLQuery:
|
|
cfg.source = SourceURLQuery
|
|
default:
|
|
panic("[session] unsupported source in KeyLookup")
|
|
}
|
|
cfg.sessionName = selectors[1]
|
|
|
|
return cfg
|
|
}
|