-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to pass the variable to 'handler'? #198
Comments
I want to get something like that (it's a plot only):
|
Hello, are you using Go 1.7+ ? I could give you and example using the |
Hello, @falmar! Thank you! Can you share an example? Yes. I'm using go 1.7.4.
|
I encourage you to use the standard This would be a standard http.Handler func getIndex(w http.ResponseWriter, r *http.Request) {
//...
// ugh... but here we don't have access to s
fmt.Println(s.Path);
//...
} Well First you would need to wrap julien's The wrapper receives a func wrapHandler(h http.Handler) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
// Take the context out from the request
ctx := r.Context()
// Get new context with key-value "params" -> "httprouter.Params"
ctx = context.WithValue(ctx, "params", ps)
// Get new http.Request with the new context
r = r.WithContext(ctx)
// Call your original http.Handler
h.ServeHTTP(w, r)
}
} You now can take the params out in your GetIndex handler func getIndex(w http.ResponseWriter, r *http.Request) {
//...
// You can take the params this way
ps, ok := r.Context().Value("params").(httprouter.Params)
if !ok {
log.Fatal("ps is not type httprouter.Params")
}
//...
} I ignore where your Settings are coming from, but there could be two approaches, use a middleware to pass the settings down the
func getIndexWithSettings(s Settings) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
//
// Settings is in the scope
fmt.Println(s.Path)
//
})
}
func getIndexWithSettings2(s Settings) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
//
// Settings is in the scope and ps httprouter.params
fmt.Println(s.Path)
//
}
}
func settingsMiddleware(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Take the context out from the request
ctx := r.Context()
// Get the settings
s := somewhere()
// Get new context with key-value "settings"
ctx = context.WithValue(ctx, "settings", s)
// Get new http.Request with the new context
r = r.WithContext(ctx)
// Call your original http.Handler
h.ServeHTTP(w, r)
})
} This is how you would use any of this approaches func main() {
r := httprouter.New()
// wrapHandler
r.GET("/index", wrapHandler(http.HandlerFunc(getIndex)))
// inject settings
r.GET("/index", getIndexWithSettings(s))
// middleware
r.GET("/index", wrapHandler(settingsMiddleware(http.HandlerFunc(getIndex))))
http.ListenAndServe(addr, r)
} But chained all this handlers and wrappers will be cumbersome you could use |
@falmar
Message error:
|
Ok, look change this func func getIndexWithSettings(s string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Println(s)
})
} for this func getIndexWithSettings(s string) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
fmt.Println(s)
}
} And you will end up with this package main
import (
"fmt"
"net/http"
"github.com/julienschmidt/httprouter"
)
func main() {
r := httprouter.New()
var s = "/var/bin"
r.GET("/index", getIndexWithSettings(s))
http.ListenAndServe(":8080", r)
}
func getIndexWithSettings(s string) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
fmt.Println(s)
}
} You should take a look at the middleware approach as a better practice when writing future programs package main
import (
"context"
"fmt"
"net/http"
"github.com/julienschmidt/httprouter"
)
func main() {
r := httprouter.New()
index := settingsMiddleware(http.HandlerFunc(getIndex))
r.GET("/index", wrapHandler(index))
http.ListenAndServe(":8080", r)
}
func wrapHandler(h http.Handler) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
// Take the context out from the request
ctx := r.Context()
ctx = context.WithValue(ctx, "params", ps)
r = r.WithContext(ctx)
h.ServeHTTP(w, r)
}
}
func settingsMiddleware(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var s = "/var/bin"
ctx := r.Context()
ctx = context.WithValue(ctx, "settings", s)
r = r.WithContext(ctx)
h.ServeHTTP(w, r)
})
}
func getIndex(w http.ResponseWriter, r *http.Request) {
s, ok := r.Context().Value("settings").(string)
if !ok {
fmt.Println("s is not type string")
}
fmt.Println(s) // "/var/bin"
} |
Thank you very much for your help! I've modified my source code and HTTP router do everything it takes! :) Now I want to force drop a connection, but that's another story. |
Signed-off-by: Aaron Schlesinger <aaron@ecomaz.net>
Hello!
My issue were not necessarily linked with julienschmidt/httprouter but I sure you can to help me.
I try to write a little application at Go for simulate a behaviour of some legacy HTTP-backends. My choice fell on julienschmidt/httprouter because this tool have an impressive performance and I found any pretty examples. But I have a trouble by the one part of code.
I need to pass the variable to 'handler'. I have an huge JSON-like structure filled by a data from the database. I need to use it in whole or in part. Of cource, I can to call the function for re-filling a structure at the everyone HTTP-request but it's too slow. I found some mentions about 'wrappers' for function but I don't know how to apply this. Besides, I'm guess that not everything is what it appears on the surface.
Could you kindly share a code for newbies like a me, please? :)
Thank you!
The text was updated successfully, but these errors were encountered: