gocraft/web — pull request #6 by hannobraun (2013-12-24 13:45:32+00:00)
Title: Clone context instead of creating a new one

This pull request modifies context creation: Instead of creating a new context on each request, a shallow copy of the context passed to New or Subrouter is created. This makes it possible to pass data into requests from the outside.

One use case for this is dependency injection. For example, the context could look like this:

type Context struct {
UserService UserService // the dependency I'd like to inject

UserName string // request-specific data
SessionId string
}

I would initialize it like this:

router := web.New(Context { UserService: myUserService }).
Middleware((*Context).VerifyUser)

And since the context of every request would be a shallow clone of my original context struct, I could access the user service from the middleware handler:

func (ctx *Context) VerifyUser(w web.ResponseWriter, r *web.Request) {
if !ctx.UserService.IsValidUser(ctx.UserName, ctx.SessionId) {
// error handling...
}

As far as I can tell, the only way to access services from inside middleware right now is to use a global variable. This is a bit messy and not very composable. So unless I'm missing something and there already is a nice solution to this problem, I'd appreciate it if you would merge this.