gocraft / web

Go Router + Middleware. Your Contexts.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Support immutable contexts

ohler opened this issue · comments

Packages like appengine and go.net/context provide contexts that are immutable – functions that modify a context return a new context with the desired changes rather than mutating an existing one. (See https://godoc.org/code.google.com/p/go.net/context#WithValue and https://cloud.google.com/appengine/docs/go/reference#Timeout as well as https://cloud.google.com/appengine/docs/go/datastore/reference#RunInTransaction , and note how http://godoc.org/github.com/mjibson/appstats expects handlers to not call appengine.NewContext, but use the context that the appstats middleware provides.)

gocraft/web makes the opposite assumption – it instantiates a new context for every request (meaningless for immutable contexts), and, IIUC, forces middleware that needs to have an effect on the context to do so through mutation – middleware receives the context object but can't pass a different context to the "next" handler function.

Is this correct? (I've only skimmed the documentation, not played with the code.) If so, what are your thoughts on this – how would you feel about extending gocraft/web to allow it to work with immutable contexts? The motto is "Go Router + Middleware. Your Contexts", after all, so immutable contexts aren't obviously out of scope; and I believe that appengine and go.net/context are setting a good precedent by providing immutable contexts, since they are automatically thread-safe, and allow setting timeouts etc. with a form of dynamic scope rather than per-request (which would force such settings to be the same across all goroutines that relate to the same request).

I haven't thought about what exactly it would take, but I think we'd need to at least allow middleware to call the "next" function with a different context; and allowing interfaces as the context type might also be helpful. I don't know if there are type system issues with either or both of these. Before I go any further – have you thought about this before and rejected it?

commented

At a bare minimum, I think this would double the number the number of signatures that gocraft/web has to deal with for middleware. Also, how do you propose handling the fact that the context type of the middleware in a subrouter can be an extension(via embedding) of the context above it? This may not be as problematic as I suspect.

Also, why do you think contexts are automatically thread-safe? Copying an object in Go does not automatically create something thread-safe. For example, go create a copy of a big.Int. You'll find that changes to the copy can affect the original.

@ohler I don't think I'm interested in supporting immutable contexts or go.net/context. They're both fine ideas, but incompatible with the design of gocraft/web.