mattes
mattes

Reputation: 9429

How to set context value inside http.HandleFunc?

I want to set a context value inside an http.HandleFunc. The following approach seems to work.

I'm a little worried about *r = *r.WithContext(ctx) though.

type contextKey string
var myContext = contextKey("myContext")

func setValue(r *http.Request, val string)  {
  ctx := context.WithValue(r.Context(), myContext, val)
  *r = *r.WithContext(ctx)
}

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

What's the best approach to set a context variable inside an http.HandleFunc?

Upvotes: 1

Views: 6268

Answers (1)

Thundercat
Thundercat

Reputation: 120941

The code in the question overwrites the request object. This can result in code up the stack using the wrong context value. Request.WithContext creates a shallow copy of the request to avoid this. Return a pointer to that shallow copy.

func setValue(r *http.Request, val string) *http.Request {
  return r.WithContext(context.WithValue(r.Context(), myContext, val))
}

http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    r = setValue(r, "foobar")
})

If then handler invokes some other handler, then pass the new request along to the new handler:

http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    r = setValue(r, "foobar")
    someOtherHandler.ServeHTTP(w, r)
})

Upvotes: 6

Related Questions