### Quick Start Implementation Source: https://github.com/boj/redistore/blob/master/README.md A complete example showing how to initialize the store and use it within an HTTP handler. ```go package main import ( "log" "net/http" "github.com/boj/redistore/v2" "github.com/gorilla/sessions" ) func main() { // Create a new store with options store, err := redistore.NewStore( redistore.KeysFromStrings("secret-key"), redistore.WithAddress("tcp", ":6379"), ) if err != nil { panic(err) } defer store.Close() http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { // Get a session session, err := store.Get(r, "session-key") if err != nil { log.Println(err.Error()) return } // Set a value session.Values["foo"] = "bar" // Save session if err = sessions.Save(r, w); err != nil { log.Fatalf("Error saving session: %v", err) } }) log.Fatal(http.ListenAndServe(":8080", nil)) } ``` -------------------------------- ### Main Server Setup Source: https://context7.com/boj/redistore/llms.txt Sets up the HTTP server, registers handlers for login, logout, profile, and health check endpoints, and starts the server on port 8080. Ensures the session store is closed upon application exit. ```go func main() { defer store.Close() http.HandleFunc("/login", loginHandler) http.HandleFunc("/logout", logoutHandler) http.HandleFunc("/profile", requireAuth(profileHandler)) http.HandleFunc("/health", healthHandler) log.Println("Server starting on :8080") log.Fatal(http.ListenAndServe(":8080", nil)) } ``` -------------------------------- ### Complete Redistore Example with Custom Configuration Source: https://github.com/boj/redistore/blob/master/README.md A full example demonstrating how to initialize redistore with various custom configurations, including keys, address, database, max length, key prefix, and default max age, and setting up HTTP handlers for session management. ```go package main import ( "log" "net/http" "github.com/boj/redistore/v2" "github.com/gorilla/sessions" ) func main() { // Initialize store with custom configuration store, err := redistore.NewStore( redistore.KeysFromStrings("secret-key-123"), redistore.WithAddress("tcp", "localhost:6379"), redistore.WithDB("1"), redistore.WithMaxLength(8192), redistore.WithKeyPrefix("webapp_"), redistore.WithDefaultMaxAge(3600), // 1 hour ) if err != nil { log.Fatal(err) } defer store.Close() http.HandleFunc("/set", func(w http.ResponseWriter, r *http.Request) { session, _ := store.Get(r, "my-session") session.Values["user"] = "john_doe" session.Values["authenticated"] = true sessions.Save(r, w) w.Write([]byte("Session saved!")) }) http.HandleFunc("/get", func(w http.ResponseWriter, r *http.Request) { session, _ := store.Get(r, "my-session") user := session.Values["user"] if user != nil { w.Write([]byte("User: " + user.(string))) } else { w.Write([]byte("No user in session")) } }) http.HandleFunc("/delete", func(w http.ResponseWriter, r *http.Request) { session, _ := store.Get(r, "my-session") session.Options.MaxAge = -1 sessions.Save(r, w) w.Write([]byte("Session deleted!")) }) log.Println("Server started on :8080") log.Fatal(http.ListenAndServe(":8080", nil)) } ``` -------------------------------- ### v2 Complete Migration Example Source: https://github.com/boj/redistore/blob/master/MIGRATION.md A full example of initializing and configuring a redistore session in v2, including closing the store. ```go package main import ( "github.com/boj/redistore/v2" "github.com/gorilla/sessions" ) func main() { store, err := redistore.NewStore( []byte("secret-key-123"), redistore.WithAddress("tcp", "localhost:6379"), redistore.WithAuth("user", "password"), redistore.WithDB("1"), redistore.WithMaxLength(8192), redistore.WithKeyPrefix("myapp_"), redistore.WithMaxAge(86400 * 7), // 7 days ) if err != nil { panic(err) } defer store.Close() // Use store... } ``` -------------------------------- ### v1 Complete Migration Example Source: https://github.com/boj/redistore/blob/master/MIGRATION.md A full example of initializing and configuring a redistore session in v1, including closing the store. ```go package main import ( "github.com/boj/redistore" "github.com/gorilla/sessions" ) func main() { store, err := redistore.NewRediStoreWithDB( 10, "tcp", "localhost:6379", "user", "password", "1", []byte("secret-key-123"), ) if err != nil { panic(err) } defer store.Close() // Configure after creation store.SetMaxLength(8192) store.SetKeyPrefix("myapp_") store.SetMaxAge(86400 * 7) // 7 days // Use store... } ``` -------------------------------- ### v1 Connection using Redis URL Source: https://github.com/boj/redistore/blob/master/MIGRATION.md Example of initializing a store using a Redis URL in v1. ```go store, err := redistore.NewRediStoreWithURL( 10, "redis://:password@localhost:6379/0", []byte("secret-key"), ) ``` -------------------------------- ### v1 Basic Connection Source: https://github.com/boj/redistore/blob/master/MIGRATION.md Example of establishing a basic connection using redistore v1. ```go store, err := redistore.NewRediStore( 10, // pool size "tcp", // network ":6379", // address "", // username "", // password []byte("secret-key"), ) ``` -------------------------------- ### v1 Connection with Authentication Source: https://github.com/boj/redistore/blob/master/MIGRATION.md Example of connecting with username and password in redistore v1. ```go store, err := redistore.NewRediStore( 10, "tcp", ":6379", "myuser", // username "mypass", // password []byte("secret-key"), ) ``` -------------------------------- ### Example Curl Command for Login Source: https://context7.com/boj/redistore/llms.txt An example command to test the login functionality using curl. It sends a POST request with username and password and saves the session cookies to 'cookies.txt'. ```bash # Login: curl -X POST -d "username=admin&password=password123" http://localhost:8080/login -c cookies.txt ``` -------------------------------- ### Install redistore Source: https://github.com/boj/redistore/blob/master/README.md Commands to install the current or legacy version of the library. ```sh go get github.com/boj/redistore/v2 ``` ```sh go get github.com/boj/redistore@v1 ``` -------------------------------- ### Handle Configuration Errors Source: https://github.com/boj/redistore/blob/master/README.md Example of how to catch and handle errors during RediStore initialization, specifically when multiple conflicting connection options are provided. ```go store, err := redistore.NewStore( [][]byte{[]byte("secret-key")}, redistore.WithAddress("tcp", ":6379"), redistore.WithURL("redis://localhost"), // ❌ Error: multiple connection options ) if err != nil { // Error: "only one connection option can be specified" log.Fatal(err) } ``` -------------------------------- ### Retrieve and Manage Sessions Source: https://context7.com/boj/redistore/llms.txt Use the Get method to retrieve or create a session. Remember to call sessions.Save to persist changes to the store. ```go package main import ( "encoding/json" "log" "net/http" "github.com/boj/redistore/v2" "github.com/gorilla/sessions" ) var store *redistore.RediStore func init() { var err error store, err = redistore.NewStore( redistore.KeysFromStrings("secret-key-32-bytes-long!!!!!!"), redistore.WithAddress("tcp", "localhost:6379"), ) if err != nil { log.Fatal(err) } } func handler(w http.ResponseWriter, r *http.Request) { // Get session (creates new if doesn't exist) session, err := store.Get(r, "user-session") if err != nil { http.Error(w, "Failed to get session: "+err.Error(), http.StatusInternalServerError) return } // Check if this is a new session if session.IsNew { log.Println("New session created") session.Values["visits"] = 0 } // Increment visit counter visits := session.Values["visits"].(int) visits++ session.Values["visits"] = visits // Save session if err := sessions.Save(r, w); err != nil { http.Error(w, "Failed to save session: "+err.Error(), http.StatusInternalServerError) return } // Return response json.NewEncoder(w).Encode(map[string]interface{}{ "visits": visits, "sessionID": session.ID, "isNew": session.IsNew, }) } func main() { defer store.Close() http.HandleFunc("/", handler) log.Fatal(http.ListenAndServe(":8080", nil)) } ``` -------------------------------- ### Run RediStore Tests Source: https://github.com/boj/redistore/blob/master/README.md Commands to start a Redis server and run the RediStore test suite, including options for generating code coverage reports. ```bash # Start Redis (required) redis-server # Run tests go test -v # With coverage go test -v -coverprofile=coverage.out go tool cover -html=coverage.out ``` -------------------------------- ### v1 Specific Database Connection Source: https://github.com/boj/redistore/blob/master/MIGRATION.md Example of connecting to a specific Redis database using NewRediStoreWithDB in v1. ```go store, err := redistore.NewRediStoreWithDB( 10, "tcp", ":6379", "", "", "5", // database []byte("secret-key"), ) ``` -------------------------------- ### Login Handler Source: https://context7.com/boj/redistore/llms.txt Handles user login requests. It validates credentials (simplified for example), sets session values like authentication status, user ID, username, login time, and IP address, and saves the session. Requires a POST request with 'username' and 'password' form values. ```go func loginHandler(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) return } username := r.FormValue("username") password := r.FormValue("password") // Validate credentials (simplified - use proper auth in production) if username != "admin" || password != "password123" { http.Error(w, "Invalid credentials", http.StatusUnauthorized) return } session, _ := store.Get(r, sessionName) // Set session values session.Values["authenticated"] = true session.Values["user_id"] = 1 session.Values["username"] = username session.Values["login_time"] = time.Now().Unix() session.Values["ip_address"] = r.RemoteAddr // Save session if err := sessions.Save(r, w); err != nil { http.Error(w, "Failed to save session", http.StatusInternalServerError) return } json.NewEncoder(w).Encode(map[string]interface{}{ "status": "success", "message": "Logged in successfully", }) } ``` -------------------------------- ### Generate Secure Random Keys for Redistore Source: https://context7.com/boj/redistore/llms.txt Generate cryptographically secure random keys for initial setup. Use these keys to initialize your redistore instance, and then store them securely. ```go newAuthKey := make([]byte, 32) newEncKey := make([]byte, 16) rand.Read(newAuthKey) rand.Read(newEncKey) log.Printf("New Auth Key: %s", hex.EncodeToString(newAuthKey)) log.Printf("New Encrypt Key: %s", hex.EncodeToString(newEncKey)) ``` -------------------------------- ### v2 Key Pairs Initialization with Helper Functions Source: https://github.com/boj/redistore/blob/master/MIGRATION.md Demonstrates v2's recommended approach using KeysFromStrings for cleaner key pair management. ```go NewStore(KeysFromStrings("secret-key"), WithAddress("tcp", ":6379")) NewStore( KeysFromStrings( "auth-key", "encrypt-key", "old-auth-key", "old-encrypt-key", ), WithAddress("tcp", ":6379"), ) NewStore(Keys([]byte("secret-key")), WithAddress("tcp", ":6379")) NewStore([][]byte{[]byte("secret-key")}, WithAddress("tcp", ":6379")) ``` -------------------------------- ### v2 Basic Connection with Option Pattern Source: https://github.com/boj/redistore/blob/master/MIGRATION.md Demonstrates establishing a basic connection in v2 using the NewStore function and options. ```go store, err := redistore.NewStore( redistore.KeysFromStrings("secret-key"), redistore.WithAddress("tcp", ":6379"), // WithPoolSize is optional (defaults to 10) ) ``` -------------------------------- ### v2 Connection with Authentication Options Source: https://github.com/boj/redistore/blob/master/MIGRATION.md Shows how to configure authentication using WithAuth and WithPassword options in v2. ```go store, err := redistore.NewStore( redistore.KeysFromStrings("secret-key"), redistore.WithAddress("tcp", ":6379"), redistore.WithAuth("myuser", "mypass"), ) // Or just password: store, err := redistore.NewStore( redistore.KeysFromStrings("secret-key"), redistore.WithAddress("tcp", ":6379"), redistore.WithPassword("mypass"), ) ``` -------------------------------- ### v1 Key Pairs Initialization Source: https://github.com/boj/redistore/blob/master/MIGRATION.md Illustrates how key pairs were handled in v1 using variadic byte slices. ```go NewRediStore(10, "tcp", ":6379", "", "", []byte("secret-key")) NewRediStore(10, "tcp", ":6379", "", "", []byte("auth-key"), []byte("encrypt-key"), []byte("old-auth-key"), []byte("old-encrypt-key")) ``` -------------------------------- ### Connection Options Reference Source: https://github.com/boj/redistore/blob/master/MIGRATION.md Lists available options for establishing a connection to Redis. ```go WithPool(pool *redis.Pool) // Use custom pool WithAddress(network, address string) // Connect via network + address WithURL(url string) // Connect via Redis URL ``` -------------------------------- ### v2 Specific Database Connection Options Source: https://github.com/boj/redistore/blob/master/MIGRATION.md Demonstrates connecting to a specific database in v2 using WithDB and WithDBNum options. ```go store, err := redistore.NewStore( redistore.KeysFromStrings("secret-key"), redistore.WithAddress("tcp", ":6379"), redistore.WithDB("5"), ) // Or using integer: store, err := redistore.NewStore( redistore.KeysFromStrings("secret-key"), redistore.WithAddress("tcp", ":6379"), redistore.WithDBNum(5), ) ``` -------------------------------- ### Initialize Redistore with Key Rotation (Strings) Source: https://github.com/boj/redistore/blob/master/README.md Use KeysFromStrings to initialize the store with new and old keys for session encryption. The first pair is used for new sessions, while all pairs are tried for decoding existing sessions. ```go // Keys are provided in pairs: authentication key, encryption key // The first pair is used for encoding new sessions // All pairs are tried for decoding existing sessions store, err := redistore.NewStore( redistore.KeysFromStrings( "new-authentication-key", // 32 or 64 bytes recommended "new-encryption-key", // 16, 24, or 32 bytes for AES "old-authentication-key", // Keep for existing sessions "old-encryption-key", // Keep for existing sessions ), redistore.WithAddress("tcp", "localhost:6379"), ) ``` -------------------------------- ### Store Configuration Options Reference Source: https://github.com/boj/redistore/blob/master/MIGRATION.md Lists available options for configuring the session store itself. ```go WithMaxLength(length int) // Max session size (default: 4096) WithKeyPrefix(prefix string) // Redis key prefix (default: "session_") WithDefaultMaxAge(age int) // Default TTL in seconds (default: 1200) WithSerializer(s SessionSerializer) // Serializer (default: GobSerializer) WithSessionOptions(opts *sessions.Options) // Full session options WithPath(path string) // Cookie path (default: "/") WithMaxAge(age int) // Cookie MaxAge (default: 30 days) ``` -------------------------------- ### Get Session Values Source: https://github.com/boj/redistore/blob/master/README.md Retrieves values associated with specific keys from the session. Always check for nil and perform type assertions. ```go session, _ := store.Get(r, "session-key") username := session.Values["username"] if username != nil { fmt.Println(username.(string)) } ``` -------------------------------- ### v2 Custom Configuration (All at Once) Source: https://github.com/boj/redistore/blob/master/MIGRATION.md Shows how to configure session parameters like MaxLength, KeyPrefix, and Serializer during redistore session creation in v2. ```go store, err := redistore.NewStore( redistore.KeysFromStrings("secret-key"), redistore.WithAddress("tcp", ":6379"), redistore.WithMaxLength(8192), redistore.WithKeyPrefix("myapp_"), redistore.WithSerializer(redistore.JSONSerializer{}), ) ``` -------------------------------- ### Migrate from RediStore v1 to v2 Source: https://github.com/boj/redistore/blob/master/README.md Compares the initialization syntax between RediStore v1 and v2, highlighting the shift towards the Option Pattern in v2. ```go // v1 store, err := redistore.NewRediStore(10, "tcp", ":6379", "", "", []byte("key")) // v2 store, err := redistore.NewStore( []byte("key"), redistore.WithAddress("tcp", ":6379"), ) ``` -------------------------------- ### Create Key Pairs with Helper Functions Source: https://github.com/boj/redistore/blob/master/CHANGELOG.md Use helper functions to simplify the creation of key pairs for the NewStore constructor. ```go store, err := NewStore(Keys([]byte("key")), WithAddress("tcp", ":6379")) ``` ```go store, err := NewStore(KeysFromStrings("secret-key"), WithAddress("tcp", ":6379")) ``` -------------------------------- ### Health Check Handler Source: https://context7.com/boj/redistore/llms.txt Checks the health of the Redis connection by attempting to get and save a session. Returns 'healthy' if successful, or 'unhealthy' with an error message if Redis is not accessible. ```go func healthHandler(w http.ResponseWriter, r *http.Request) { // Test Redis connection via session store session, err := store.Get(r, "health-check") if err != nil { w.WriteHeader(http.StatusServiceUnavailable) json.NewEncoder(w).Encode(map[string]string{"status": "unhealthy", "error": err.Error()}) return } session.Values["check"] = time.Now().Unix() if err := sessions.Save(r, w); err != nil { w.WriteHeader(http.StatusServiceUnavailable) json.NewEncoder(w).Encode(map[string]string{"status": "unhealthy", "error": err.Error()}) return } json.NewEncoder(w).Encode(map[string]string{"status": "healthy"}) } ``` -------------------------------- ### v1 Custom Configuration (Post-Creation) Source: https://github.com/boj/redistore/blob/master/MIGRATION.md Demonstrates setting session parameters like MaxLength, KeyPrefix, and Serializer after creating a redistore session in v1. ```go store, err := redistore.NewRediStore(10, "tcp", ":6379", "", "", []byte("secret-key")) store.SetMaxLength(8192) store.SetKeyPrefix("myapp_") store.SetSerializer(redistore.JSONSerializer{}) ``` -------------------------------- ### Redistore v2: Correct Connection Option Usage Source: https://github.com/boj/redistore/blob/master/MIGRATION.md To correctly initialize redistore, choose a single connection method like WithAddress. This ensures proper configuration and avoids connection errors. ```go // Choose ONE connection method store, err := redistore.NewStore( redistore.KeysFromStrings("secret-key"), redistore.WithAddress("tcp", ":6379"), // ✅ Only one ) ``` -------------------------------- ### Pitfall: Empty Key Pairs Fix Source: https://github.com/boj/redistore/blob/master/MIGRATION.md Demonstrates the correct way to provide key pairs when initializing a redistore session to avoid errors. ```go store, err := redistore.NewStore( [][]byte{[]byte("secret-key")}, // ✅ Provide key redistore.WithAddress("tcp", ":6379"), ) ``` -------------------------------- ### v2 Use Existing Pool Source: https://github.com/boj/redistore/blob/master/MIGRATION.md Shows how to initialize a redistore session in v2 by providing an existing custom redis.Pool. ```go pool := &redis.Pool{ MaxIdle: 100, IdleTimeout: 5 * time.Minute, Dial: func() (redis.Conn, error) { return redis.Dial("tcp", ":6379") }, } store, err := redistore.NewStore( [][]byte{[]byte("secret-key")}, redistore.WithPool(pool), ) ``` -------------------------------- ### Authentication Options Reference Source: https://github.com/boj/redistore/blob/master/MIGRATION.md Lists available options for Redis authentication. ```go WithAuth(username, password string) // Set both username and password WithPassword(password string) // Set password only ``` -------------------------------- ### Manage Redis Sessions with RediStore Source: https://context7.com/boj/redistore/llms.txt Demonstrates initializing a RediStore instance and handling login, update, and logout operations using standard HTTP handlers. ```go package main import ( "log" "net/http" "time" "github.com/boj/redistore/v2" "github.com/gorilla/sessions" ) var store *redistore.RediStore func init() { var err error store, err = redistore.NewStore( redistore.KeysFromStrings("secret-key-32-bytes-long!!!!!!"), redistore.WithAddress("tcp", "localhost:6379"), redistore.WithDefaultMaxAge(3600), // 1 hour default TTL ) if err != nil { log.Fatal(err) } } func loginHandler(w http.ResponseWriter, r *http.Request) { session, _ := store.Get(r, "auth-session") // Store user data in session session.Values["user_id"] = 12345 session.Values["username"] = "john_doe" session.Values["email"] = "john@example.com" session.Values["authenticated"] = true session.Values["login_time"] = time.Now().Unix() // Save session to Redis if err := sessions.Save(r, w); err != nil { http.Error(w, "Failed to save session", http.StatusInternalServerError) return } w.Write([]byte("Login successful")) } func updateHandler(w http.ResponseWriter, r *http.Request) { session, _ := store.Get(r, "auth-session") // Update session values session.Values["last_activity"] = time.Now().Unix() // Extend session expiry (optional) session.Options.MaxAge = 7200 // 2 hours // Save changes if err := sessions.Save(r, w); err != nil { http.Error(w, "Failed to update session", http.StatusInternalServerError) return } w.Write([]byte("Session updated")) } func logoutHandler(w http.ResponseWriter, r *http.Request) { session, _ := store.Get(r, "auth-session") // Mark session for deletion session.Options.MaxAge = -1 // Save (this deletes from Redis and expires cookie) if err := sessions.Save(r, w); err != nil { http.Error(w, "Failed to delete session", http.StatusInternalServerError) return } w.Write([]byte("Logged out successfully")) } func main() { defer store.Close() http.HandleFunc("/login", loginHandler) http.HandleFunc("/update", updateHandler) http.HandleFunc("/logout", logoutHandler) log.Fatal(http.ListenAndServe(":8080", nil)) } ``` -------------------------------- ### Implement Flash Messages in Go Source: https://context7.com/boj/redistore/llms.txt Demonstrates initializing a RediStore, adding flash messages, and retrieving them using the gorilla/sessions API. ```go package main import ( "html/template" "log" "net/http" "github.com/boj/redistore/v2" "github.com/gorilla/sessions" ) var store *redistore.RediStore var templates = template.Must(template.New("").Parse(`
{{range .Flashes}}