Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I pass data from middleware to handlers?

Tags:

I am designing my handlers to return a http.Handler. Here's the design of my handlers:

 func Handler() http.Handler {
  return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  })
}

My middleware is designed to accept an http.Handler and then call the handler once the middleware has finished performing its operations. Here's the design of my middleware:

 func Middleware(next http.Handler) http.Handler {
  return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    // Middleware operations

    next.ServeHTTP(w, r)
  })
}

Considering the design of my middleware and handlers, what is the proper way of passing information from the middleware to the handler? The information that I am trying to pass from my middleware to the handlers is a JSON web token parsed from the request body. If I do not pass the parsed JWT to the handler, then I will need to parse the JWT again in my handlers. Parsing the request body for a JWT in both the middleware and handler seems wasteful. Just in case this information is relevant, I am using the standard net/http library with gorilla mux.

like image 365
Dipen Avatar asked Jul 19 '15 18:07

Dipen


2 Answers

Since you're already using Gorilla take a look at the context package.

(This is nice if you don't want to change your method signatures.)

import (
    "github.com/gorilla/context"
)

...

func Middleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // Middleware operations
        // Parse body/get token.
        context.Set(r, "token", token)

        next.ServeHTTP(w, r)
    })
}

...

func Handler() http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        token := context.Get(r, "token")
    })
}

Update

The Gorilla context package is now in maintenance mode
per the repo:

Note gorilla/context, having been born well before context.Context existed, does not play well with the shallow copying of the request that http.Request.WithContext (added to net/http Go 1.7 onwards) performs.

Using gorilla/context may lead to memory leaks under those conditions, as the pointers to each http.Request become "islanded" and will not be cleaned up when the response is sent.

You should use the http.Request.Context() feature in Go 1.7.

like image 122
Justin Avatar answered Oct 22 '22 02:10

Justin


The proper way to pass request scoped data would now be the context package in the standard library.

https://golang.org/pkg/context/

You can access it with request.Context on an http.Request.

like image 20
Kenny Grant Avatar answered Oct 22 '22 04:10

Kenny Grant