xhandler

package
v1.4.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 10, 2016 License: GPL-3.0, MIT Imports: 3 Imported by: 0

README

XHandler

godoc license Build Status Coverage

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.

Installing

go get -u github.com/rs/xhandler

Usage

package main

import (
	"log"
	"net/http"
	"time"

	"github.com/rs/cors"
	"github.com/rs/xhandler"
	"golang.org/x/net/context"
)

type myMiddleware struct {
	next xhandler.HandlerC
}

func (h myMiddleware) ServeHTTPC(ctx context.Context, w http.ResponseWriter, r *http.Request) {
	ctx = context.WithValue(ctx, "test", "World")
	h.next.ServeHTTPC(ctx, w, r)
}

func main() {
	c := xhandler.Chain{}

	// Add close notifier handler so context is cancelled when the client closes
	// the connection
	c.UseC(xhandler.CloseHandler)

	// Add timeout handler
	c.UseC(xhandler.TimeoutHandler(2 * time.Second))

	// Middleware putting something in the context
	c.UseC(func(next xhandler.HandlerC) xhandler.HandlerC {
		return myMiddleware{next: next}
	})

	// Mix it with a non-context-aware middleware handler
	c.Use(cors.Default().Handler)

	// Final handler (using handlerFuncC), reading from the context
	xh := 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))

	if err := http.ListenAndServe(":8080", nil); err != nil {
		log.Fatal(err)
	}
}
Using xmux

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"
)

func main() {
	c := xhandler.Chain{}

	// Append a context-aware middleware handler
	c.UseC(xhandler.CloseHandler)

	// Another context-aware middleware handler
	c.UseC(xhandler.TimeoutHandler(2 * time.Second))

	mux := xmux.New()

	// Use c.Handler to terminate the chain with your final handler
	mux.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"))
	}))

	if err := http.ListenAndServe(":8080", c.Handler(mux)); err != nil {
		log.Fatal(err)
	}
}

See xmux for more examples.

Context Aware Middleware

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

Licenses

All source code is licensed under the MIT License.

Documentation

Overview

Package xhandler provides a bridge between http.Handler and net/context.

xhandler enforces 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 in when the client close the connection unexpectedly.

You may create net/context aware middlewares pretty much the same way as you would do with http.Handler.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func If

func If(cond func(ctx context.Context, w http.ResponseWriter, r *http.Request) bool, condNext func(next HandlerC) HandlerC) func(next HandlerC) HandlerC

If is a special handler that will skip insert the condNext handler only if a condition applies at runtime.

func New

func New(ctx context.Context, h HandlerC) http.Handler

New creates a conventional http.Handler injecting the provided root context to sub handlers. This handler is used as a bridge between conventional http.Handler and context aware handlers.

func TimeoutHandler

func TimeoutHandler(timeout time.Duration) func(next HandlerC) HandlerC

TimeoutHandler returns a Handler which adds a timeout to the context.

Child handlers have the responsability to obey the context deadline and to return an appropriate error (or not) response in case of timeout.

Types

type Chain

type Chain []func(next HandlerC) HandlerC

Chain is an helper to chain middleware handlers together for an easier management.

func (Chain) Handler

func (c Chain) Handler(xh HandlerC) http.Handler

Handler wraps the provided final handler with all the middleware appended to the chain and return a new standard http.Handler instance. The context.Background() context is injected automatically.

func (Chain) HandlerC

func (c Chain) HandlerC(xh HandlerC) HandlerC

HandlerC wraps the provided final handler with all the middleware appended to the chain and returns a HandlerC instance.

func (Chain) HandlerCF

func (c Chain) HandlerCF(xhc HandlerFuncC) HandlerC

HandlerCF wraps the provided final handler func with all the middleware appended to the chain and returns a HandlerC instance.

HandlerCF is equivalent to:

c.HandlerC(xhandler.HandlerFuncC(xhc))

func (Chain) HandlerCtx

func (c Chain) HandlerCtx(ctx context.Context, xh HandlerC) http.Handler

HandlerCtx wraps the provided final handler with all the middleware appended to the chain and return a new standard http.Handler instance.

func (Chain) HandlerF

func (c Chain) HandlerF(hf http.HandlerFunc) http.Handler

HandlerF is an helper to provide a standard http handler function (http.HandlerFunc) to Handler(). Your final handler won't have access the context though.

func (Chain) HandlerFC

func (c Chain) HandlerFC(xhf HandlerFuncC) http.Handler

HandlerFC is an helper to provide a function (HandlerFuncC) to Handler().

HandlerFC is equivalent to:

c.Handler(xhandler.HandlerFuncC(xhc))

func (Chain) HandlerH

func (c Chain) HandlerH(h http.Handler) http.Handler

HandlerH is an helper to provide a standard http handler (http.HandlerFunc) to Handler(). Your final handler won't have access the context though.

func (*Chain) Use

func (c *Chain) Use(f func(next http.Handler) http.Handler)

Use appends a standard http.Handler to the middleware chain without lossing track of the context when inserted between two context aware handlers.

Caveat: the f function will be called on each request so you are better to put any initialization sequence outside of this function.

func (*Chain) UseC

func (c *Chain) UseC(f func(next HandlerC) HandlerC)

UseC appends a context-aware handler to the middleware chain.

type HandlerC

type HandlerC interface {
	ServeHTTPC(context.Context, http.ResponseWriter, *http.Request)
}

HandlerC is a net/context aware http.Handler

func CloseHandler

func CloseHandler(next HandlerC) HandlerC

CloseHandler returns a Handler cancelling the context when the client connection close unexpectedly.

type HandlerFuncC

type HandlerFuncC func(context.Context, http.ResponseWriter, *http.Request)

HandlerFuncC type is an adapter to allow the use of ordinary functions as a xhandler.Handler. If f is a function with the appropriate signature, xhandler.HandlerFuncC(f) is a xhandler.Handler object that calls f.

func (HandlerFuncC) ServeHTTPC

func (f HandlerFuncC) ServeHTTPC(ctx context.Context, w http.ResponseWriter, r *http.Request)

ServeHTTPC calls f(ctx, w, r).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL