Adding upstream version 2.52.6.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
a960158181
commit
6d002e9543
441 changed files with 95392 additions and 0 deletions
136
middleware/session/store.go
Normal file
136
middleware/session/store.go
Normal file
|
@ -0,0 +1,136 @@
|
|||
package session
|
||||
|
||||
import (
|
||||
"encoding/gob"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v2/internal/storage/memory"
|
||||
"github.com/gofiber/fiber/v2/utils"
|
||||
)
|
||||
|
||||
// ErrEmptySessionID is an error that occurs when the session ID is empty.
|
||||
var ErrEmptySessionID = errors.New("session id cannot be empty")
|
||||
|
||||
// sessionIDKey is the local key type used to store and retrieve the session ID in context.
|
||||
type sessionIDKey int
|
||||
|
||||
const (
|
||||
// sessionIDContextKey is the key used to store the session ID in the context locals.
|
||||
sessionIDContextKey sessionIDKey = iota
|
||||
)
|
||||
|
||||
type Store struct {
|
||||
Config
|
||||
}
|
||||
|
||||
// New creates a new session store with the provided configuration.
|
||||
func New(config ...Config) *Store {
|
||||
// Set default config
|
||||
cfg := configDefault(config...)
|
||||
|
||||
if cfg.Storage == nil {
|
||||
cfg.Storage = memory.New()
|
||||
}
|
||||
|
||||
return &Store{
|
||||
cfg,
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterType registers a custom type for encoding/decoding into any storage provider.
|
||||
func (*Store) RegisterType(i interface{}) {
|
||||
gob.Register(i)
|
||||
}
|
||||
|
||||
// Get retrieves or creates a session for the given context.
|
||||
func (s *Store) Get(c *fiber.Ctx) (*Session, error) {
|
||||
var rawData []byte
|
||||
var err error
|
||||
|
||||
id, ok := c.Locals(sessionIDContextKey).(string)
|
||||
if !ok {
|
||||
id = s.getSessionID(c)
|
||||
}
|
||||
|
||||
fresh := ok // Assume the session is fresh if the ID is found in locals
|
||||
|
||||
// Attempt to fetch session data if an ID is provided
|
||||
if id != "" {
|
||||
rawData, err = s.Storage.Get(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if rawData == nil {
|
||||
// Data not found, prepare to generate a new session
|
||||
id = ""
|
||||
}
|
||||
}
|
||||
|
||||
// Generate a new ID if needed
|
||||
if id == "" {
|
||||
fresh = true // The session is fresh if a new ID is generated
|
||||
id = s.KeyGenerator()
|
||||
c.Locals(sessionIDContextKey, id)
|
||||
}
|
||||
|
||||
// Create session object
|
||||
sess := acquireSession()
|
||||
|
||||
sess.mu.Lock()
|
||||
defer sess.mu.Unlock()
|
||||
|
||||
sess.ctx = c
|
||||
sess.config = s
|
||||
sess.id = id
|
||||
sess.fresh = fresh
|
||||
|
||||
// Decode session data if found
|
||||
if rawData != nil {
|
||||
sess.data.Lock()
|
||||
defer sess.data.Unlock()
|
||||
if err := sess.decodeSessionData(rawData); err != nil {
|
||||
return nil, fmt.Errorf("failed to decode session data: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return sess, nil
|
||||
}
|
||||
|
||||
// getSessionID returns the session ID from cookies, headers, or query string.
|
||||
func (s *Store) getSessionID(c *fiber.Ctx) string {
|
||||
id := c.Cookies(s.sessionName)
|
||||
if len(id) > 0 {
|
||||
return utils.CopyString(id)
|
||||
}
|
||||
|
||||
if s.source == SourceHeader {
|
||||
id = string(c.Request().Header.Peek(s.sessionName))
|
||||
if len(id) > 0 {
|
||||
return id
|
||||
}
|
||||
}
|
||||
|
||||
if s.source == SourceURLQuery {
|
||||
id = c.Query(s.sessionName)
|
||||
if len(id) > 0 {
|
||||
return utils.CopyString(id)
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// Reset deletes all sessions from the storage.
|
||||
func (s *Store) Reset() error {
|
||||
return s.Storage.Reset()
|
||||
}
|
||||
|
||||
// Delete deletes a session by its ID.
|
||||
func (s *Store) Delete(id string) error {
|
||||
if id == "" {
|
||||
return ErrEmptySessionID
|
||||
}
|
||||
return s.Storage.Delete(id)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue