In my AuthMw middleware, I want to make database calls.
My database variable is initialized in main, how can I pass this to my middleware AuthMw?
func main() {
db, err := gorm.Open("postgres", ... )
r := mux.NewRouter()
r.Handle("/ws", serveWebsocket(hub))
r.Use(AuthMw)
//
//
...
} // main
func AuthMw(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
token := r.URL.Query().Get("token")
fmt.Printf("AuthMiddleware token is: %v
", token)
ctx := ....
next.ServeHTTP(w, r.WithContext(ctx))
})
}
You have two straight-forward options that doesn't involve global variables.
You could re-write AuthMw
into:
func AuthMw(db *DbType) (func (next http.Handler) http.Handler) {
return func (next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Your code goes here, now with a pointer to db
})
}
}
That way, you make a "factory function" that returns a new http.Handler
decorator, where your db
variable is accessible throught the closure.
All you need to do after this is to replace r.Use(AuthMw)
with r.Use(AuthMw(db))
.
This is maybe a little heavy on nested methods, so I'll instead suggest...
Turn AuthMw
into a struct with you decorator attached as a method:
type AuthMw struct {
db *DbType
}
func NewAuthMw(db *DbType) AuthMw {
return AuthMw{db}
}
func (a *AuthMw) Decorator(next http.Handler) http.Handler {
// Your code, now with a pointer to db, goes here
}
Then you just need replace r.Use(AuthMw)
with r.Use(authMwVariable.Decorator)
.