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.

Context-Aware Handler Chains in Go (using Stack)

Note: As of Go 1.7+ the context package is now part of Go's standard library and you should use that to pass data between your handlers. Joe Shaw has made a good tutorial here. If you're using a Go version < 1.7 then the information below may still be useful.

I've written a package for chaining context-aware handlers in Go, called Stack (view it on Github). It was heavily inspired by Alice.

What do you mean by 'context-aware'?

If you're using a middleware pattern to process HTTP requests in Go, you may want to share some data or context between middleware handlers and your application handlers. For example you might want to:

Use some middleware to create a CRSF token, and later render the token to a template in your application handler. Or perhaps...

Authenticate a user in one middleware handler, and then pass the user details to a second middleware handler which checks if the user is authorised to access the resource.

There are a few packages that can help with this. Matt Silverlock has written a good article about some of the different approaches and tools – I won't rehash it here, instead I recommend giving it a read.

Why make another package?

Because none of the existing tools seemed ideal – at least to me. Gorilla Context is simple and very flexible, but relies on a global context map and you remembering to clear the context after each request. (It's still my favourite though). Goji provides request-scoped context, which is good, but it's part of a larger package and ties you into using the Goji router. The same is true of Gocraft/web, which also relies on reflection tricks under the hood that I struggle to wrap my head around.

I realised that the only time you need to worry about context is when you're chaining handlers together. So I looked at my favorite tool for chaining handlers, Alice, and began adapting that to create Stack.

I wanted the package to:

Do a simple job, and then get out of the way.

Provide a request-scoped context map.

map. Let you create stackable, reusable, handler chains in the Alice style.

in the Alice style. Be as type-safe at compile time as it possibly could be.

at compile time as it possibly could be. Be simple to understand and non-magic .

. Operate nicely with existing standards. In particular:

The handler chain must satisfy the http.Handler interface , so it can be used with the http.DefaultServeMux .

, so it can be used with the .

It should be compatible with the func(http.Handler) http.Handler pattern commonly used by third-party middleware packages.

The full documentation for Stack is here, but here's a quick example of how to use it:

File: main.go package main import ( "fmt" "github.com/alexedwards/stack" "github.com/goji/httpauth" "net/http" ) func main() { // Setup goji/httpauth, some third-party middleware authenticate := stack.Middleware(httpauth.SimpleBasicAuth("user", "pass")) // Create a handler chain and register it with the DefaultServeMux http.Handle("/", stack.New(authenticate, tokenMiddleware).Then(tokenHandler)) http.ListenAndServe(":3000", nil) } func tokenMiddleware(ctx stack.Context, next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Add a value to Context with the key 'token' ctx["token"] = "c9e452805dee5044ba520198628abcaa" next.ServeHTTP(w, r) }) } func tokenHandler(ctx stack.Context) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Retrieve the token from Context and print it fmt.Fprintf(w, "Token is: %s", ctx["token"]) }) }