Building Middleware with Negroni
Reasons use middleware, including logging requests, authenticating and authorizing users, and mapping resources.
Idiomatic HTTP Middleware for Golang. https://github.com/urfave/negroni
Install the negroni package.
go get github.com/urfave/negroni
PS: How to solve the go get can not work in China. Following is the best solution so far. https://github.com/goproxy/goproxy.cn
$ go env -w GO111MODULE=on $ go env -w GOPROXY=https://goproxy.cn,direct
Negroni example
package main import ( "github.com/gorilla/mux" "github.com/urfave/negroni" "net/http" ) func main() { r := mux.NewRouter() n := negroni.Classic() n.UseHandler(r) http.ListenAndServe(":8000",n) }
Build and execute this program.
Create trivial middleware that prints a message and passes execution to the next middleware in the chain:
package main import ( "fmt" "github.com/gorilla/mux" "github.com/urfave/negroni" "net/http" ) type trivial struct { } func (t *trivial) ServeHTTP(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { fmt.Println("Executing trivial middleware") next(w, r) } func main() { r := mux.NewRouter() n := negroni.Classic() n.UseHandler(r) n.Use(&trivial{}) http.ListenAndServe(":8000",n) }
Build and test this new program.
Adding Authentication with Negroni
Use of context, which can easily pass variables between functions.
package main import ( "context" "fmt" "net/http" "github.com/gorilla/mux" "github.com/urfave/negroni" ) type badAuth struct { Username string Password string } func (b *badAuth) ServeHTTP(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { username := r.URL.Query().Get("username") password := r.URL.Query().Get("password") if username != b.Username && password !=b.Password { http.Error(w, "Unauthorized", 401) return } ctx := context.WithValue(r.Context(), "username", username) r = r.WithContext(ctx) next(w, r) } func hello(w http.ResponseWriter, r * http.Request) { username := r.Context().Value("username").(string) fmt.Fprintf(w, "Hi %s ", username) } func main() { r := mux.NewRouter() r.HandleFunc("/hello",hello).Methods("GET") n := negroni.Classic() n.Use(&badAuth{ Username: "admin", Password: "password", }) n.UseHandler(r) http.ListenAndServe(":8000", n) }
Build and excute this program. Then test it by sending a few requests to the server.
curl -i http://localhost:8000/hello curl -i 'http://localhost:8000/hello?username=admin&password=password'
Logs on the server-side.