Best way to include additional parameters to handler?

966 views
Skip to first unread message

Rodney Brown

unread,
Jan 13, 2015, 9:30:35 PM1/13/15
to goril...@googlegroups.com
I am looking at using Gorilla Sessions and want to also move to Gorilla Mux as well.

In my current go project, my go script is generating some data that most, if not all of the handlers need to have.

Currently I'm using the following code to add the additional parameter (we'll call it extraData):

http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
indexHandler(w, r, extraData)
})


Is there a way to do this with Gorilla Mux or should I be using pointers instead?

Mahmud Ridwan

unread,
Jan 13, 2015, 11:47:01 PM1/13/15
to goril...@googlegroups.com
You could try using Gorilla context. Your handlers could look like this eventually:
 
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
  // Generate extra data and put them in Gorilla context
  // ...
 
  // Invoke actual handler
  indexHandler(w, r)
})
 
And inside your actual handlers, you could then retrieve those extra data from Gorilla context.
 
 
This way, it is also possible to write a function which can take your actual handler as an argument, and return a new handler that can do the task of the handler shown above.
--
You received this message because you are subscribed to the Google Groups "Gorilla web toolkit" group.
To unsubscribe from this group and stop receiving emails from it, send an email to gorilla-web...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
 

Matt Silverlock

unread,
Jan 15, 2015, 6:18:52 PM1/15/15
to goril...@googlegroups.com
A little more modular/re-usable - not tested, as it's been a while since I've written any Go code, but it should be at least 95% of the way there:

type key int
const mwKey key = 0

func YourMiddleware(h http.HandlerFunc) http.HandlerFunc {
    // do the thing you need
    // get the value

    // store it in the context, below
    fn := func(w http.ResponseWriter, r *http.Request) {
        context.Set(r, mwKey, "whatyouwanttostore")

        h.ServeHTTP(w, r)
    }

    return fn
}

func YourHandler(w http.ResponseWriter, r *http.Request) {
    val, ok := context.Get(r, mwKey)
    // Type assert - we'll assume it's a string we want
    if !val.(string) {
        // Handle the case where the "wrong" type has
        // been stored in our context against the
        // expected key. HTTP 500 recommended here.
    }

}

func main() {
    http.HandleFunc("/", YourMiddleware(YourHandler))

    http.ListenAndServe(":8000", nil)

Mahmud Ridwan

unread,
Jan 16, 2015, 12:29:20 AM1/16/15
to goril...@googlegroups.com
I noticed that you are "retrieving" the values outside of the generated handler func, but storing them in context only when this handler is invoked. Which is fine, as long as the values that you are retrieving do not change throughout the programs lifetime. 
 
But just in case that is not what you want. You might want to tweak your `YourMiddleware` func to look like this:
 
func YourMiddleware(h http.HandlerFunc) http.HandlerFunc {
    fn := func(w http.ResponseWriter, r *http.Request) {
        // do the thing you need
        // get the value
        // doing this inside fn ensures this is one every time a request comes in for the handler `h`
 
        // store it in the context, below
        context.Set(r, mwKey, "whatyouwanttostore")
 
        h.ServeHTTP(w, r)
    }
 
    return fn
}
 
 
On a side note, `context.Get` might have a different signature. If I recall right, it only returns one value (an interface{}):
 
val := context.Get(r, mwKey)
 
Best regards,
Ridwan
Reply all
Reply to author
Forward
0 new messages