gorilla/context

How to access object property after it's passed through context.

bachvtuan opened this issue · 2 comments

Hi. I'm facing a problem that I passed my object through the context. I get it but I can't access it own property.
here is my code.
I define my struct

type Config  struct{
    DbName  string
    DbHost string
        ApiKey string
}

next I init the object

_config = Config{"my_db_name","127.0.0.1","top-secret"}

In first handler I set to the context

context.Set(r, "config", config)

And I get it from next handler

    _config := context.Get(r, "config")
     test_config, found := _config.(config.Config)

     if found{
      fmt.Println(  "wrong" ) 
     }

     fmt.Println( test_config.DbName)

and I see test_config.DbName is empty. when I tried to dump as json string, it's still print value correctly.
For now, I have only a way is encode and decode json again and it worked but it make slow down my code for parsing time.
Any Idea to fix this ?
Thank

Some questions:

  • Can you show more of your program? (both handlers - where you set/get from the context)
  • Are the handlers operating on the same request?
  • Did you typo the below, or is this how it is in your program?
_config := context.Get(r, "config")
test_config, found := _config.(config.Config)

// This will print "wrong" when the config *exists*
if found{
   fmt.Println(  "wrong" ) 
}

 // This will print the value of test_config.DbName even if it doesn't exist
fmt.Println( test_config.DbName)

The idiom for type asserting from a map is typically closer to the below:

config, ok := context.Get(r, "config").(config.Config)
if !ok { 
    // Handle the case where the config is not as expected
    // Make sure to return early or otherwise "bail out"
    return
}

// Given the above, you can now assume that config was retrieved and is of the correct type

Thank you for help make my code look neater. I see my problem now.

At the "set" step

context.Set(r, "config", _config)
varriable _config is type *config.Config. it's a pointer

func wrapHandler(h http.Handler, _config *config.Config) httprouter.Handle {
  return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {

    context.Set(r, "params", ps)
    //Set config as well
    context.Set(r, "config", _config)

    h.ServeHTTP(w, r)
  }
}

when I change type to config.Config.

func wrapHandler(h http.Handler, _config config.Config) httprouter.Handle {
  return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {

    context.Set(r, "params", ps)
    //Set config as well
    context.Set(r, "config", _config)

    h.ServeHTTP(w, r)
  }
}

It' worked :)