Skip to content

Instantly share code, notes, and snippets.

@omeid
Last active August 29, 2015 14:09
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save omeid/8246f4094bca78a69bb0 to your computer and use it in GitHub Desktop.
Node.js (Express) Style Go Middleware in 40 line of code.
package main
import (
"log"
"net/http"
"time"
)
type Handler func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)
type stack struct {
handler Handler
next *stack
}
var noop = &stack{func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {}, &stack{}}
func (s stack) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
s.handler(rw, r, s.next.ServeHTTP)
}
func App(handle Handler) *stack {
return &stack{handle, noop}
}
func (s *stack) Use(handler Handler) *stack {
if s.next != noop {
return s.next.Use(handler)
}
s.next = &stack{handler, noop}
return s
}
func (s *stack) Run(addr string) {
log.Printf("Listening on: %s\n\n", addr)
log.Fatal(http.ListenAndServe(addr, s))
}
//Example Usage:
func logger(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
start := time.Now()
log.Printf("Started %s %s", r.Method, r.URL.Path)
next(rw, r)
log.Printf("Completed %s %s in %v\n\n", r.Method, r.URL.Path, time.Since(start))
}
// Wrapper for http.Handlers
func Wrap(h http.Handler) Handler {
return func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
h.ServeHTTP(rw, r)
next(rw, r)
}
}
func main() {
fs := http.FileServer(http.Dir("/usr/share/doc"))
app := App(logger)
app.Use(Wrap(fs))
//Oh, and print the useragent IP.
app.Use(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
log.Printf("Useragent IP %s", r.RemoteAddr)
next(rw, r)
})
//Now lets run it!
app.Run(":8080")
//as 'stack' is a http.Handler, so you can use it like this too.
//log.Fatal(http.ListenAndServe(":8080", app))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment