XHandler is a bridge between net/context and http.Handler.
It lets you enforce net/context in your handlers without sacrificing compatibility with existing http.Handlers nor imposing a specific router.
Thanks to net/context deadline management, xhandler is able to enforce a per request deadline and will cancel the context when the client closes the connection unexpectedly.
You may create your own net/context aware handler pretty much the same way as you would do with http.Handler.
Read more about xhandler on Dailymotion engineering blog.
go get -u github.com/rs/xhandler
package main
import (
"log""net/http""time""github.com/rs/cors""github.com/rs/xhandler""golang.org/x/net/context"
)
typemyMiddlewarestruct {
next xhandler.HandlerC
}
func (hmyMiddleware) ServeHTTPC(ctx context.Context, w http.ResponseWriter, r*http.Request) {
ctx=context.WithValue(ctx, "test", "World")
h.next.ServeHTTPC(ctx, w, r)
}
funcmain() {
c:= xhandler.Chain{}
// Add close notifier handler so context is cancelled when the client closes// the connectionc.UseC(xhandler.CloseHandler)
// Add timeout handlerc.UseC(xhandler.TimeoutHandler(2*time.Second))
// Middleware putting something in the contextc.UseC(func(next xhandler.HandlerC) xhandler.HandlerC {
returnmyMiddleware{next: next}
})
// Mix it with a non-context-aware middleware handlerc.Use(cors.Default().Handler)
// Final handler (using handlerFuncC), reading from the contextxh:=xhandler.HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r*http.Request) {
value:=ctx.Value("test").(string)
w.Write([]byte("Hello "+value))
})
// Bridge context aware handlers with http.Handler using xhandler.Handle()http.Handle("/test", c.Handler(xh))
iferr:=http.ListenAndServe(":8080", nil); err!=nil {
log.Fatal(err)
}
}Xhandler comes with an optional context aware muxer forked from httprouter:
package main
import (
"fmt""log""net/http""time""github.com/rs/xhandler""github.com/rs/xmux""golang.org/x/net/context"
)
funcmain() {
c:= xhandler.Chain{}
// Append a context-aware middleware handlerc.UseC(xhandler.CloseHandler)
// Another context-aware middleware handlerc.UseC(xhandler.TimeoutHandler(2*time.Second))
mux:=xmux.New()
// Use c.Handler to terminate the chain with your final handlermux.GET("/welcome/:name", xhandler.HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, req*http.Request) {
fmt.Fprintf(w, "Welcome %s!", xmux.Params(ctx).Get("name"))
}))
iferr:=http.ListenAndServe(":8080", c.Handler(mux)); err!=nil {
log.Fatal(err)
}
}See xmux for more examples.
Here is a list of net/context aware middleware handlers implementing xhandler.HandlerC interface.
Feel free to put up a PR linking your middleware if you have built one:
| Middleware | Author | Description |
|---|---|---|
| xmux | Olivier Poitrey | HTTP request muxer |
| xlog | Olivier Poitrey | HTTP handler logger |
| xstats | Olivier Poitrey | A generic client for service instrumentation |
| xaccess | Olivier Poitrey | HTTP handler access logger with xlog and xstats |
| cors | Olivier Poitrey | Cross Origin Resource Sharing (CORS) support |
All source code is licensed under the MIT License.