Skip to content

Instantly share code, notes, and snippets.

@mtilson
Last active December 31, 2019 02:52
Show Gist options
  • Save mtilson/9b945b00a3d282e17cd7a6996162def5 to your computer and use it in GitHub Desktop.
Save mtilson/9b945b00a3d282e17cd7a6996162def5 to your computer and use it in GitHub Desktop.
how to create middleware with net/http Handle() by implementing own Handler interface [golang]
package main
import (
"log"
"net/http"
)
type myHandler http.HandlerFunc
func (f myHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
log.Println("do something always")
f(w, r)
}
func main() {
http.Handle("/abc", abcMiddleware(doABC))
http.Handle("/abc/by-pass-abc-middleware", doABC)
http.Handle("/xyz", xyzMiddleware(doXYZ))
http.Handle("/xyz/by-pass-xyz-middleware", doXYZ)
http.ListenAndServe(":8080", nil)
}
var doABC myHandler = func(w http.ResponseWriter, r *http.Request) {
log.Println("do something every time ABC handler invoked")
w.WriteHeader(http.StatusOK)
}
func abcMiddleware(next http.Handler) http.Handler {
log.Println("do something only once on ABC middleware init")
return myHandler(func(w http.ResponseWriter, r *http.Request) {
log.Println("do something every time middleware for ABC handler invoked ")
next.ServeHTTP(w, r)
})
}
var doXYZ myHandler = func(w http.ResponseWriter, r *http.Request) {
log.Println("do something every time XYZ handler invoked")
w.WriteHeader(http.StatusOK)
}
func xyzMiddleware(next http.Handler) http.Handler {
log.Println("do something only once on XYZ middleware init")
return myHandler(func(w http.ResponseWriter, r *http.Request) {
log.Println("do something every time middleware for XYZ handler invoked")
next.ServeHTTP(w, r)
})
}
$ go run main.go
2019/12/31 05:47:47 do something only once on ABC middleware init
2019/12/31 05:47:47 do something only once on XYZ middleware init
>>>
>>> get http://localhost:8080/abc
>>>
2019/12/31 05:47:54 do something always
2019/12/31 05:47:54 do something every time middleware for ABC handler invoked
2019/12/31 05:47:54 do something always
2019/12/31 05:47:54 do something every time ABC handler invoked
>>>
>>> get http://localhost:8080/abc/by-pass-abc-middleware
>>>
2019/12/31 05:49:21 do something always
2019/12/31 05:49:21 do something every time ABC handler invoked
>>>
>>> get http://localhost:8080/xyz/by-pass-xyz-middleware
>>>
2019/12/31 05:50:53 do something always
2019/12/31 05:50:53 do something every time XYZ handler invoked
>>>
>>> get http://localhost:8080/xyz
>>>
2019/12/31 05:51:49 do something always
2019/12/31 05:51:49 do something every time middleware for XYZ handler invoked
2019/12/31 05:51:49 do something always
2019/12/31 05:51:49 do something every time XYZ handler invoked
@mtilson
Copy link
Author

mtilson commented Dec 20, 2019

Avoid usage of DefaultServeMux in production code due to its security risk

  • DefaultServeMux is global variable and if you accidentally import any compromised third-party package, it could potentially register a route in DefaultServeMux and expose to the world some malicious handler
  • You can use ServeMux locally scoped (to the func main() in the example above) and returned with http.NewServeMux()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment