Skip to content

Cookies & Sessions

Cookies and sessions are essential for maintaining state in web applications. This section covers cookie management, session handling, and security best practices for stateful HTTP applications.

http.SetCookie(response, name, value, options)

Sets a cookie in the HTTP response.

Syntax:

SetCookie Syntax
http.SetCookie(response, name, value, options) (error)

Parameters: - response (map) - Response writer object - name (string) - Cookie name - value (string) - Cookie value - options (map) - Cookie options (domain, path, expires, etc.)

Examples:

Basic Cookie Setting:

Basic Cookie Setting
package main
import http
import fmt

function setCookieHandler(request map, response map) {
    // Set a simple cookie
    http.SetCookie(response, "user_preference", "dark_theme", {})

    // Set a cookie with options
    http.SetCookie(response, "session_id", "abc123xyz", {
        "httpOnly": true,        // Prevent JavaScript access
        "secure": true,          // HTTPS only
        "sameSite": "strict",    // CSRF protection
        "maxAge": 3600,          // 1 hour expiration
        "path": "/",             // Available site-wide
        "domain": ".example.com" // Available on subdomains
    })

    // Set a persistent cookie (expires in 30 days)
    var thirtyDaysFromNow = getCurrentTimestamp() + (30 * 24 * 3600)
    http.SetCookie(response, "remember_me", "true", {
        "expires": thirtyDaysFromNow,
        "httpOnly": true,
        "secure": true,
        "sameSite": "lax"
    })

    http.WriteResponse(response, 200, "text/plain", "Cookies set successfully")
}

Cookie Configuration Options:

Cookie Configuration
package main
import http

// Comprehensive cookie configuration
function setSecureCookie(response map, name string, value string) {
    var cookieOptions = {
        "httpOnly": true,           // Prevent XSS attacks
        "secure": true,             // HTTPS only
        "sameSite": "strict",       // CSRF protection
        "maxAge": 3600,             // 1 hour
        "path": "/",                // Available site-wide
        "domain": "",               // Current domain only
    }

    http.SetCookie(response, name, value, cookieOptions)
}

// Session cookie (expires when browser closes)
function setSessionCookie(response map, name string, value string) {
    var sessionOptions = {
        "httpOnly": true,
        "secure": true,
        "sameSite": "strict",
        "path": "/"
        // No maxAge or expires = session cookie
    }

    http.SetCookie(response, name, value, sessionOptions)
}

// Persistent cookie (long-term storage)
function setPersistentCookie(response map, name string, value string, days int) {
    var expirationTime = getCurrentTimestamp() + (days * 24 * 3600)

    var persistentOptions = {
        "httpOnly": true,
        "secure": true,
        "sameSite": "lax",
        "expires": expirationTime,
        "path": "/"
    }

    http.SetCookie(response, name, value, persistentOptions)
}

http.GetCookie(request, name)

Gets a cookie value from the HTTP request.

Syntax:

GetCookie Syntax
http.GetCookie(request, name) (value, error)

Parameters: - request (map) - Request object - name (string) - Cookie name

Examples:

Reading Cookies:

Reading Cookies
package main
import http
import json
import fmt

function getCookieHandler(request map, response map) {
    // Get a specific cookie
    var sessionResult = http.GetCookie(request, "session_id")
    var sessionId = sessionResult[0]
    var sessionErr = sessionResult[1]

    if sessionErr != None {
        fmt.Printf("No session cookie found: %s\n", sessionErr)
    } else {
        fmt.Printf("Session ID: %s\n", sessionId)
    }

    // Get user preferences
    var themeResult = http.GetCookie(request, "user_preference")
    var theme = themeResult[0]
    var themeErr = themeResult[1]

    var responseData = {
        "sessionId": sessionId,
        "theme": theme,
        "hasSession": sessionErr == None,
        "hasTheme": themeErr == None
    }

    var jsonData, _ = json.Marshal(responseData)
    http.WriteResponse(response, 200, "application/json", jsonData)
}

// Get all cookies from request
function getAllCookies(request map) {
    var cookies = request["cookies"]
    if cookies == None {
        return {}
    }
    return cookies
}

function listCookiesHandler(request map, response map) {
    var allCookies = getAllCookies(request)

    var cookieList = []
    for name, value in allCookies {
        cookieList = append(cookieList, {
            "name": name,
            "value": value
        })
    }

    var responseData = {
        "cookies": cookieList,
        "count": len(cookieList)
    }

    var jsonData, _ = json.Marshal(responseData)
    http.WriteResponse(response, 200, "application/json", jsonData)
}

Delete Cookie
package main
import http

// Delete a cookie by setting it to expire immediately
function deleteCookie(response map, name string) {
    http.SetCookie(response, name, "", {
        "httpOnly": true,
        "secure": true,
        "sameSite": "strict",
        "maxAge": -1,    // Expire immediately
        "path": "/"
    })
}

function deleteCookieHandler(request map, response map) {
    var query = request["query"]
    var cookieName = query["name"]

    if cookieName == None or cookieName == "" {
        http.WriteResponse(response, 400, "application/json", "{\"error\": \"Cookie name required\"}")
        return
    }

    deleteCookie(response, cookieName)

    var responseData = {
        "message": "Cookie deleted",
        "cookieName": cookieName
    }

    var jsonData, _ = json.Marshal(responseData)
    http.WriteResponse(response, 200, "application/json", jsonData)
}

Session Management

Session Store Implementation

Session Store
package main
import http
import json
import fmt

// In-memory session store (use Redis/database in production)
var sessionStore = {}

// Session structure
type Session struct {
    id string
    userId string
    data map
    createdAt int
    lastAccessed int
    expiresAt int
}

// Create a new session
function createSession(userId string, sessionData map) {
    var sessionId = generateSessionId()
    var currentTime = getCurrentTimestamp()

    var session = {
        "id": sessionId,
        "userId": userId,
        "data": sessionData,
        "createdAt": currentTime,
        "lastAccessed": currentTime,
        "expiresAt": currentTime + 3600  // 1 hour default
    }

    sessionStore[sessionId] = session
    return session
}

// Get session by ID
function getSession(sessionId string) {
    var session = sessionStore[sessionId]

    if session == None {
        return None
    }

    // Check if session is expired
    if isSessionExpired(session) {
        delete(sessionStore, sessionId)
        return None
    }

    // Update last accessed time
    session["lastAccessed"] = getCurrentTimestamp()
    return session
}

// Update session data
function updateSession(sessionId string, data map) {
    var session = sessionStore[sessionId]
    if session != None {
        session["data"] = data
        session["lastAccessed"] = getCurrentTimestamp()
        return true
    }
    return false
}

// Destroy session
function destroySession(sessionId string) {
    delete(sessionStore, sessionId)
}

// Check if session is expired
function isSessionExpired(session map) {
    var expiresAt = session["expiresAt"]
    var currentTime = getCurrentTimestamp()
    return currentTime > expiresAt
}

// Generate secure session ID
function generateSessionId() {
    // In a real implementation, use cryptographically secure random generator
    return "sess_" + generateRandomString(64)
}

// Clean up expired sessions (run periodically)
function cleanupExpiredSessions() {
    var currentTime = getCurrentTimestamp()
    var expiredSessions = []

    for sessionId, session in sessionStore {
        if currentTime > session["expiresAt"] {
            expiredSessions = append(expiredSessions, sessionId)
        }
    }

    for sessionId in expiredSessions {
        delete(sessionStore, sessionId)
    }

    fmt.Printf("Cleaned up %d expired sessions\n", len(expiredSessions))
}

Session Middleware

Session Middleware
package main
import http
import fmt

// Session middleware that loads session data into request
function sessionMiddleware(next function) {
    return function(request map, response map) {
        var sessionId = getSessionIdFromCookie(request)

        if sessionId != "" {
            var session = getSession(sessionId)
            if session != None {
                // Add session to request context
                request["session"] = session
                request["sessionId"] = sessionId
                request["userId"] = session["userId"]
                request["sessionData"] = session["data"]
            }
        }

        next(request, response)
    }
}

function getSessionIdFromCookie(request map) {
    var cookieResult = http.GetCookie(request, "session_id")
    var sessionId = cookieResult[0]
    var err = cookieResult[1]

    if err != None {
        return ""
    }

    return sessionId
}

// Session-aware handler example
function sessionAwareHandler(request map, response map) {
    var session = request["session"]
    var sessionData = request["sessionData"]

    if session == None {
        // No session - show login prompt
        var responseData = {
            "authenticated": false,
            "message": "Please log in"
        }
        var jsonData, _ = json.Marshal(responseData)
        http.WriteResponse(response, 401, "application/json", jsonData)
        return
    }

    // Session exists - show user data
    var responseData = {
        "authenticated": true,
        "userId": session["userId"],
        "sessionData": sessionData,
        "lastAccessed": session["lastAccessed"]
    }

    var jsonData, _ = json.Marshal(responseData)
    http.WriteResponse(response, 200, "application/json", jsonData)
}

Login with Session Creation

Login Session
package main
import http
import json
import fmt

function loginWithSessionHandler(request map, response map) {
    var method = request["method"]

    if method != "POST" {
        http.WriteResponse(response, 405, "application/json", "{\"error\": \"Method not allowed\"}")
        return
    }

    var body = request["body"]
    var loginData, parseErr = json.Unmarshal(body)

    if parseErr != None {
        http.WriteResponse(response, 400, "application/json", "{\"error\": \"Invalid JSON\"}")
        return
    }

    var username = loginData["username"]
    var password = loginData["password"]
    var rememberMe = loginData["rememberMe"]

    // Authenticate user
    var user = authenticateUser(username, password)
    if user == None {
        http.WriteResponse(response, 401, "application/json", "{\"error\": \"Invalid credentials\"}")
        return
    }

    // Create session with user data
    var sessionData = {
        "username": user["username"],
        "email": user["email"],
        "roles": user["roles"],
        "loginTime": getCurrentTimestamp()
    }

    var session = createSession(user["id"], sessionData)

    // Set session cookie
    var cookieOptions = {
        "httpOnly": true,
        "secure": true,
        "sameSite": "strict",
        "path": "/"
    }

    // Set expiration based on "remember me"
    if rememberMe == true {
        cookieOptions["maxAge"] = 30 * 24 * 3600  // 30 days
        session["expiresAt"] = getCurrentTimestamp() + (30 * 24 * 3600)
    } else {
        // Session cookie (expires when browser closes)
        session["expiresAt"] = getCurrentTimestamp() + 3600  // 1 hour
    }

    http.SetCookie(response, "session_id", session["id"], cookieOptions)

    var loginResponse = {
        "success": true,
        "user": {
            "id": user["id"],
            "username": user["username"],
            "email": user["email"]
        },
        "sessionId": session["id"]
    }

    var jsonData, _ = json.Marshal(loginResponse)
    http.WriteResponse(response, 200, "application/json", jsonData)
}

function logoutWithSessionHandler(request map, response map) {
    var sessionId = getSessionIdFromCookie(request)

    if sessionId != "" {
        destroySession(sessionId)
    }

    // Clear session cookie
    deleteCookie(response, "session_id")

    var logoutResponse = {
        "success": true,
        "message": "Logged out successfully"
    }

    var jsonData, _ = json.Marshal(logoutResponse)
    http.WriteResponse(response, 200, "application/json", jsonData)
}

Shopping Cart Example

Shopping Cart
package main
import http
import json
import fmt

// Shopping cart using sessions
function addToCartHandler(request map, response map) {
    var method = request["method"]

    if method != "POST" {
        http.WriteResponse(response, 405, "application/json", "{\"error\": \"Method not allowed\"}")
        return
    }

    var body = request["body"]
    var cartData, parseErr = json.Unmarshal(body)

    if parseErr != None {
        http.WriteResponse(response, 400, "application/json", "{\"error\": \"Invalid JSON\"}")
        return
    }

    var productId = cartData["productId"]
    var quantity = cartData["quantity"]

    if productId == None or quantity == None {
        http.WriteResponse(response, 400, "application/json", "{\"error\": \"Product ID and quantity required\"}")
        return
    }

    // Get or create session
    var sessionId = getSessionIdFromCookie(request)
    var session = None

    if sessionId != "" {
        session = getSession(sessionId)
    }

    if session == None {
        // Create new session for anonymous user
        session = createSession("anonymous", {"cart": {}})

        http.SetCookie(response, "session_id", session["id"], {
            "httpOnly": true,
            "secure": true,
            "sameSite": "strict",
            "maxAge": 3600,  // 1 hour
            "path": "/"
        })
    }

    // Get current cart
    var sessionData = session["data"]
    var cart = sessionData["cart"]
    if cart == None {
        cart = {}
    }

    // Add item to cart
    var currentQuantity = cart[productId]
    if currentQuantity == None {
        currentQuantity = 0
    }
    cart[productId] = currentQuantity + quantity

    // Update session
    sessionData["cart"] = cart
    updateSession(session["id"], sessionData)

    var cartResponse = {
        "success": true,
        "cart": cart,
        "itemCount": getCartItemCount(cart)
    }

    var jsonData, _ = json.Marshal(cartResponse)
    http.WriteResponse(response, 200, "application/json", jsonData)
}

function getCartHandler(request map, response map) {
    var sessionId = getSessionIdFromCookie(request)
    var cart = {}

    if sessionId != "" {
        var session = getSession(sessionId)
        if session != None {
            var sessionData = session["data"]
            cart = sessionData["cart"]
            if cart == None {
                cart = {}
            }
        }
    }

    var cartResponse = {
        "cart": cart,
        "itemCount": getCartItemCount(cart),
        "total": calculateCartTotal(cart)
    }

    var jsonData, _ = json.Marshal(cartResponse)
    http.WriteResponse(response, 200, "application/json", jsonData)
}

function getCartItemCount(cart map) {
    var count = 0
    for productId, quantity in cart {
        count = count + quantity
    }
    return count
}

function calculateCartTotal(cart map) {
    // In a real implementation, look up product prices
    var total = 0.0
    for productId, quantity in cart {
        var price = getProductPrice(productId)  // Mock function
        total = total + (price * quantity)
    }
    return total
}

Security Best Practices

Secure Cookie Config
package main
import http

// Production-ready secure cookie settings
function setSecureSessionCookie(response map, sessionId string) {
    var secureOptions = {
        "httpOnly": true,        // Prevent XSS attacks
        "secure": true,          // HTTPS only
        "sameSite": "strict",    // CSRF protection
        "maxAge": 3600,          // 1 hour expiration
        "path": "/",             // Available site-wide
        "domain": "",            // Current domain only (no subdomains)
    }

    http.SetCookie(response, "session_id", sessionId, secureOptions)
}

// Development cookie settings (less restrictive)
function setDevelopmentCookie(response map, name string, value string) {
    var devOptions = {
        "httpOnly": true,
        "secure": false,         // Allow HTTP in development
        "sameSite": "lax",       // Less restrictive for development
        "maxAge": 3600,
        "path": "/"
    }

    http.SetCookie(response, name, value, devOptions)
}

Session Security

Session Security
package main
import http
import fmt

// Session security middleware
function sessionSecurityMiddleware(next function) {
    return function(request map, response map) {
        var sessionId = getSessionIdFromCookie(request)

        if sessionId != "" {
            var session = getSession(sessionId)

            if session != None {
                // Check for session hijacking
                if detectSessionHijacking(request, session) {
                    fmt.Printf("Potential session hijacking detected for session: %s\n", sessionId)
                    destroySession(sessionId)
                    deleteCookie(response, "session_id")

                    http.WriteResponse(response, 401, "application/json", "{\"error\": \"Session security violation\"}")
                    return
                }

                // Regenerate session ID periodically
                if shouldRegenerateSessionId(session) {
                    var newSessionId = regenerateSessionId(session)
                    http.SetCookie(response, "session_id", newSessionId, {
                        "httpOnly": true,
                        "secure": true,
                        "sameSite": "strict",
                        "maxAge": 3600,
                        "path": "/"
                    })
                }
            }
        }

        next(request, response)
    }
}

function detectSessionHijacking(request map, session map) {
    // Check IP address consistency
    var currentIP = getClientIP(request)
    var sessionIP = session["data"]["ipAddress"]

    if sessionIP != None and sessionIP != currentIP {
        return true
    }

    // Check User-Agent consistency
    var currentUA = request["headers"]["User-Agent"]
    var sessionUA = session["data"]["userAgent"]

    if sessionUA != None and sessionUA != currentUA {
        return true
    }

    return false
}

function shouldRegenerateSessionId(session map) {
    var lastRegeneration = session["data"]["lastRegeneration"]
    var currentTime = getCurrentTimestamp()

    // Regenerate every 30 minutes
    return lastRegeneration == None or (currentTime - lastRegeneration) > 1800
}

function regenerateSessionId(oldSession map) {
    var newSessionId = generateSessionId()
    var oldSessionId = oldSession["id"]

    // Copy session data to new ID
    oldSession["id"] = newSessionId
    oldSession["data"]["lastRegeneration"] = getCurrentTimestamp()

    sessionStore[newSessionId] = oldSession
    delete(sessionStore, oldSessionId)

    return newSessionId
}

CSRF Protection with Sessions

CSRF Protection
package main
import http
import json

// Generate CSRF token for session
function generateCSRFToken(sessionId string) {
    var token = generateRandomString(32)
    var session = getSession(sessionId)

    if session != None {
        session["data"]["csrfToken"] = token
        updateSession(sessionId, session["data"])
    }

    return token
}

// CSRF protection middleware using sessions
function sessionCSRFMiddleware(next function) {
    return function(request map, response map) {
        var method = request["method"]

        // Only check CSRF for state-changing methods
        if method == "POST" or method == "PUT" or method == "DELETE" or method == "PATCH" {
            var sessionId = getSessionIdFromCookie(request)
            var session = getSession(sessionId)

            if session == None {
                http.WriteResponse(response, 401, "application/json", "{\"error\": \"No session found\"}")
                return
            }

            var sessionCSRFToken = session["data"]["csrfToken"]
            var requestCSRFToken = request["headers"]["X-CSRF-Token"]

            if sessionCSRFToken == None or requestCSRFToken == None or sessionCSRFToken != requestCSRFToken {
                http.WriteResponse(response, 403, "application/json", "{\"error\": \"CSRF token mismatch\"}")
                return
            }
        }

        next(request, response)
    }
}

// Endpoint to get CSRF token
function getCSRFTokenHandler(request map, response map) {
    var sessionId = getSessionIdFromCookie(request)

    if sessionId == "" {
        http.WriteResponse(response, 401, "application/json", "{\"error\": \"No session found\"}")
        return
    }

    var csrfToken = generateCSRFToken(sessionId)

    var tokenResponse = {
        "csrfToken": csrfToken
    }

    var jsonData, _ = json.Marshal(tokenResponse)
    http.WriteResponse(response, 200, "application/json", jsonData)
}

Complete Session-Based Application

Complete Session App
package main
import http
import json
import fmt

// Complete session-based web application setup
function setupSessionBasedApp() {
    var mux = http.NewMux()[0]

    // Public routes
    http.HandleFunc(mux, "/", homeHandler)
    http.HandleFunc(mux, "/login", loginWithSessionHandler)
    http.HandleFunc(mux, "/register", registerHandler)

    // Session-protected routes
    var sessionMux = http.NewMux()[0]

    // Apply session middleware to all protected routes
    var sessionHandler = sessionMiddleware(sessionMux)

    // Protected endpoints
    http.HandleFunc(sessionMux, "/profile", profileHandler)
    http.HandleFunc(sessionMux, "/logout", logoutWithSessionHandler)
    http.HandleFunc(sessionMux, "/cart", getCartHandler)
    http.HandleFunc(sessionMux, "/cart/add", addToCartHandler)
    http.HandleFunc(sessionMux, "/csrf-token", getCSRFTokenHandler)

    // Mount session-protected routes
    http.Handle(mux, "/app/", http.StripPrefix("/app", sessionHandler))

    return mux
}

function startSessionServer() {
    var mux = setupSessionBasedApp()
    var server = http.NewServer(":8080")[0]

    // Add security middleware
    var secureHandler = chainMiddleware([
        loggingMiddleware,
        corsMiddleware,
        securityHeadersMiddleware,
        sessionSecurityMiddleware,
        sessionCSRFMiddleware
    ])(mux)

    http.SetHandler(server, secureHandler)

    // Start session cleanup routine
    go cleanupExpiredSessions()  // Run in background

    fmt.Println("🍪 Session-based server starting on :8080")
    http.ListenAndServe(server)
}

Best Practices Summary

  • Always use httpOnly for session cookies
  • Use secure flag for HTTPS
  • Set appropriate sameSite values
  • Use reasonable expiration times

2. Session Management

  • Generate cryptographically secure session IDs
  • Store minimal data in sessions
  • Implement session expiration and cleanup
  • Regenerate session IDs periodically

3. Security Measures

  • Implement CSRF protection
  • Detect and prevent session hijacking
  • Use secure cookie configurations
  • Validate session integrity

4. Performance

  • Clean up expired sessions regularly
  • Use external session stores (Redis) for scalability
  • Implement session data compression if needed
  • Monitor session storage usage

Next Steps