Not sure how to structure your Go web application?

My new book guides you through the start-to-finish build of a real world web application in Go — covering topics like how to structure your code, manage dependencies, create dynamic database-driven pages, and how to authenticate and authorize users securely.

Take a look!

SCS: A session manager for Go

Last updated:

I’ve just released version 2 of SCS, a session management package for Go 1.11+. You can view it on GitHub.

Its design leverages Go’s context package to automatically load and save session data via middleware.

Importantly, it also provides the security features that you need when using server-side session stores (like straightforward session token regeneration) and supports both absolute and inactivity timeouts. The session data is safe for concurrent use.

A simple example

SCS supports a variety of different session stores:

Package
boltstore BoltDB based session store
memstore In-memory session store (default)
mysqlstore MySQL based session store
postgresstore PostgreSQL based session store
redisstore Redis based session store

To use the in-memory store, for example:

File: main.go
package main

import (
	"io"
	"net/http"

	"github.com/alexedwards/scs/v2"
	"github.com/alexedwards/scs/v2/memstore"
)

var session *scs.Session

func main() {
	// Initialize a new session manager and configure it to use memstore as
	// the session store.
	session = scs.NewSession()
	session.Store = memstore.New()

	mux := http.NewServeMux()
	mux.HandleFunc("/put", putHandler)
	mux.HandleFunc("/get", getHandler)

    // Wrap your handlers with the LoadAndSave() middleware.
	http.ListenAndServe(":4000", session.LoadAndSave(mux))
}

func putHandler(w http.ResponseWriter, r *http.Request) {
    // Store a new key and value in the session data.
	session.Put(r.Context(), "message", "Hello from a session!")
}

func getHandler(w http.ResponseWriter, r *http.Request) {
    // Use the GetString helper to retrieve the string value associated with a
	// key. The zero value is returned if the key does not exist.
	msg := session.GetString(r.Context(), "message")
	io.WriteString(w, msg)
}

You should be able to verify that the session data is being across requests with curl:

$ curl -i --cookie-jar cj --cookie cj localhost:4000/put
HTTP/1.1 200 OK
Cache-Control: no-cache="Set-Cookie"
Set-Cookie: session=lHqcPNiQp_5diPxumzOklsSdE-MJ7zyU6kjch1Ee0UM; Path=/; Expires=Sat, 27 Apr 2019 10:28:20 GMT; Max-Age=86400; HttpOnly; SameSite=Lax
Vary: Cookie
Date: Fri, 26 Apr 2019 10:28:19 GMT
Content-Length: 0

$ curl -i --cookie-jar cj --cookie cj localhost:4000/get
HTTP/1.1 200 OK
Date: Fri, 26 Apr 2019 10:28:24 GMT
Content-Length: 21
Content-Type: text/plain; charset=utf-8

Hello from a session!

The complete godocs are here.

I’d love to hear any feedback – either drop me an email or open an issue on GitHub.