Skip to content

Instantly share code, notes, and snippets.

@ydnar
Last active December 26, 2017 01:24
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ydnar/666f0bf5945d76592616 to your computer and use it in GitHub Desktop.
Save ydnar/666f0bf5945d76592616 to your computer and use it in GitHub Desktop.
hitch: middleware + routing for vanilla go http.Handlers — https://github.com/nbio/hitch
package main
import (
"fmt"
"net/http"
"github.com/nbio/hitch"
"github.com/nbio/httpcontext"
"github.com/nbio/httpgzip"
)
func main() {
h := hitch.New()
h.Use(Logger, httpgzip.GzipResponse, SetUser)
h.Get("/", http.HandlerFunc(Home))
items := hitch.New()
items.Use(NestedMiddleware)
items.Get("/items", http.HandlerFunc(Items))
items.Get("/items/:id", http.HandlerFunc(Item))
h.Next(items)
http.ListenAndServe(":8000", h)
}
func Logger(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
fmt.Printf("%s %s\n", req.Method, req.URL.String())
next.ServeHTTP(w, req)
})
}
type key int
const userKey key = 0
// SetUser middleware sets the User member of a RequestContext for
// subsequent handlers to depend on.
func SetUser(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
req.ParseForm()
user := req.Form.Get("user")
w.Header().Set("X-User", user)
httpcontext.Set(req, userKey, user)
next.ServeHTTP(w, req)
})
}
func Home(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Content-Type", "text/plain")
fmt.Fprintf(w, "Welcome home, %s!\n", httpcontext.GetString(req, userKey))
}
func NestedMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
w.Header().Set("X-Nested-Middleware", "active")
next.ServeHTTP(w, req)
})
}
func Items(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Content-Type", "text/plain")
fmt.Fprintf(w, "Showing all items\n")
}
func Item(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Content-Type", "text/plain")
fmt.Fprintf(w, "Showing item: %s\n", hitch.Params(req).ByName("id"))
}
Copy link

ghost commented Mar 5, 2015

$ go build hitch-example.go

./hitch.go:21: cannot use items (type *hitch.Hitch) as type http.Handler in argument to h.Next:
*hitch.Hitch does not implement http.Handler (missing ServeHTTP method)
./hitch.go:23: cannot use h (type *hitch.Hitch) as type http.Handler in argument to http.ListenAndServe:
*hitch.Hitch does not implement http.Handler (missing ServeHTTP method)

Copy link

ghost commented Mar 5, 2015

Should be:

12 func main() {
13     h := hitch.New()
14     h.Use(Logger, httpgzip.GzipResponse, SetUser)
15     h.Get("/", http.HandlerFunc(Home))
16 
17     items := hitch.New()
18     items.Use(NestedMiddleware)
19     items.Get("/items", http.HandlerFunc(Items))
20     items.Get("/items/:id", http.HandlerFunc(Item))
21     h.Next(items.Handler())
22 
23     http.ListenAndServe(":8000", h.Handler())
24 }

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