We saw in the last part that with a simple function like func (http.Handler) http.Handler we could create middlewares and share pieces of code between our routes and even our different apps. We took two examples: logging and panic recovery. But most middlewares will be more complex than that. And for some cases we will need to pass values to the next middlewares.

For example with an authentication middleware that would check if a user exists in the database and retrieve it. We need this information down the middleware stack and in the handler processing the request. This article will show you the different value sharing solutions also known as contexts.

How developers are handling it

In Ruby, most developers and frameworks are using Rack. Each middleware gets an env hash map containing request information and in which you can set anything.

In Node.js, there is Connect.js. Each middleware has two objects, one for the request and one for the response. Objects in Javascript can act as hash maps so developers are using the request object to store anything they want.

For a statically-typed language, it's not that different. I used Netty in Java a few times and it uses maps too. Each handler will have access to a context object containing an attribute map.

But how Go packages/frameworks are handling contexts? Here's a few examples.

Gorilla

gorilla/context defines a map of requests each containing a map[interface{}]interface{}] used to store information during the request processing. It uses a mutex to keep it threadsafe. Here's how it looks like:

var (
  mutex sync.RWMutex
  data  = make(map[*http.Request]map[interface{}]interface{})
)

And here's how to get and set a value:

func myHandler(w http.ResponseWriter, r *http.Request) {
  context.Set(r, "foo", "bar")
}

func myOtherHandler(w http.ResponseWriter, r *http.Request) {
  val := context.Get(r, "foo").(string)
}

The map is not cleared automatically. Each request will add an entry and the map will grow indefinitely. So Gorilla also has a handler to clear the map from the current request we must use before the end of the processing (it is automatic when used in conjonction to gorilla/mux).

Pros:

Cons:

Goji