Skip to content

Instantly share code, notes, and snippets.

@kevburnsjr
Created July 23, 2017 21:45
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save kevburnsjr/0ae92357d2e64d84b8a857764361c9c2 to your computer and use it in GitHub Desktop.
Save kevburnsjr/0ae92357d2e64d84b8a857764361c9c2 to your computer and use it in GitHub Desktop.
Easy Middleware in Go
package main
import (
"net/http"
"time"
"log"
)
func main() {
dh := DispatchHandler{}
dh.Attach(DontCache)
dh.Attach(Timer)
dh.Finalize(Router)
h := &http.Server{Addr: ":80", Handler: dh}
h.ListenAndServe()
}
// Dispatch Handler
type DispatchHandler struct {
stack []func(next func(w http.ResponseWriter, r *http.Request)) func(w http.ResponseWriter, r *http.Request)
final func(w http.ResponseWriter, r *http.Request)
}
func (h *DispatchHandler) Attach(m func(func(w http.ResponseWriter, r *http.Request)) func(w http.ResponseWriter, r *http.Request)) {
h.stack = append(h.stack, m)
}
func (h *DispatchHandler) Finalize(final func(w http.ResponseWriter, r *http.Request)) {
h.final = final
for i := len(h.stack); i > 0; i-- {
h.final = h.stack[i-1](h.final)
}
}
func (h DispatchHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
h.final(w, r)
}
// Middleware
func DontCache(next func(w http.ResponseWriter, r *http.Request)) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Cache-Control", "max-age=0, no-cache, must-revalidate")
next(w, r)
}
}
func Timer(next func(w http.ResponseWriter, r *http.Request)) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
next(w, r)
log.Printf("%d %s", time.Since(start).Nanoseconds() / 1e3, r.URL.Path)
}
}
// Router
var routes = map[string]func(http.ResponseWriter, *http.Request){
"/": IndexHandler,
"/hello": HelloHandler,
"/world": WorldHandler,
"/panic": PanicHandler,
}
func Router(w http.ResponseWriter, r *http.Request) {
if handle, ok := routes[r.URL.Path]; ok {
handle(w, r)
} else {
http.Error(w, "Not Found : "+r.URL.Path, 404)
}
}
func IndexHandler(w http.ResponseWriter, r *http.Request) {
http.Error(w, "Hello, World!", 200)
}
func HelloHandler(w http.ResponseWriter, r *http.Request) {
http.Error(w, "Hello", 200)
}
func WorldHandler(w http.ResponseWriter, r *http.Request) {
http.Error(w, "World", 200)
}
func PanicHandler(w http.ResponseWriter, r *http.Request) {
log.Panic("REM WAS RIGHT")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment