Documentation ¶
Overview ¶
Package httpctx provides a convenient way to handle HTTP requests using "context-aware" handler functions. The "context-aware" handler functions are different from the standard http.Handler functions in two important ways:
1. They accept an additional parameter of the (almost) standard type context.Context (golang.org/x/net/context); and
2. They return an error result.
Passing a context.Context to the handler functions is a useful addition because the handler functions can make use of any values associated with the context; and also because the Done channel of the context will be closed if the HTTP client closes the connection prematurely; or a timeout period has elapsed.
Returning an error value simplifies error handling in the handler functions. Common error handling is provided, which can be enhanced by middleware.
A simple middleware mechanism is also provided by this package. A middleware function is one that accepts a httpctx.Handler as a parameter and returns a httpctx.Handler as a result. (Thanks to Justinas Stankevičius for the idea for this. See github.com/justinas/alice).
Example ¶
package main import ( "context" "net/http" "github.com/spkg/httpctx" ) func main() { public := httpctx.Use(ensureHttps) authenticate := public.Use(authenticate, ensureAdmin) http.Handle("/admin", authenticate.HandleFunc(admin)) http.Handle("/", public.HandleFunc(index)) http.ListenAndServe(":8080", nil) } func index(ctx context.Context, w http.ResponseWriter, r *http.Request) error { w.Write([]byte("index page")) return nil } func admin(ctx context.Context, w http.ResponseWriter, r *http.Request) error { w.Write([]byte("admin page, userid=" + useridFrom(ctx))) return nil } // ensureHttps is an example of middleware that ensures that the request scheme is https. func ensureHttps(h httpctx.Handler) httpctx.Handler { return httpctx.HandlerFunc(func(ctx context.Context, w http.ResponseWriter, r *http.Request) error { if r.URL.Scheme != "https" { u := *r.URL u.Scheme = "https" http.Redirect(w, r, u.String(), http.StatusMovedPermanently) return nil } return h.ServeHTTPContext(ctx, w, r) }) } // authenticate is an example of middleware that authenticates using basic authentication func authenticate(h httpctx.Handler) httpctx.Handler { return httpctx.HandlerFunc(func(ctx context.Context, w http.ResponseWriter, r *http.Request) error { credentials := r.Header.Get("WWW-Authenticate") ctx, err := checkCredentials(ctx, credentials) if err != nil { return err } return h.ServeHTTPContext(ctx, w, r) }) } func ensureAdmin(h httpctx.Handler) httpctx.Handler { return httpctx.HandlerFunc(func(ctx context.Context, w http.ResponseWriter, r *http.Request) error { // ... get the userid from the context and ensure that the user has admin privilege ... return h.ServeHTTPContext(ctx, w, r) }) } // checkCredentials is a placeholder for a function that checks // credentials, and if successful returns a context with the // identity of the user attached as a value. func checkCredentials(ctx context.Context, credentials string) (context.Context, error) { // ... just an example ... // Note that you would not normally use a string as the key to context.WithValue return context.WithValue(ctx, "userid", "username"), nil } func useridFrom(ctx context.Context) string { userid, _ := ctx.Value("userid").(string) return userid }
Output:
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Handler ¶
type Handler interface {
ServeHTTPContext(ctx context.Context, w http.ResponseWriter, r *http.Request) error
}
The Handler interface used for registering handlers that serve a particular path or subtree in the HTTP server. If the ServeHTTPContext function returns an error, it is returned to the client as a HTTP error code.
type HandlerFunc ¶
The HandlerFunc type is an adapter to allow the use of ordinary functions as HTTP handlers. If f is a function with the appropriate signature, HandlerFunc(f) is a Handler object that calls f.
func (HandlerFunc) ServeHTTPContext ¶
func (f HandlerFunc) ServeHTTPContext(ctx context.Context, w http.ResponseWriter, r *http.Request) error
ServeHTTPContext calls f(ctx, w, r)
type Stack ¶
type Stack struct {
// contains filtered or unexported fields
}
A Stack is a stack of middleware functions that are common to one or more HTTP handlers. A middleware function is any function that accepts a Handler as a parameter and returns a Handler.
func Context ¶
Context returns a middleware stack that applies the context to any handlers added to the stack. This is useful when the main program creates a context that should be used as the base context for all HTTP handlers.
Example ¶
package main import ( "context" "net/http" "github.com/spkg/httpctx" ) func main() { ctx := context.Background() // Create a new context based on the background context. // For example, cancel on SIGINT and/or SIGTERM. ctx = makeNewContext(ctx) // Any call using the public stack will be passed ctx // instead of the background context for the handlers // in the stack. public := httpctx.Context(ctx).Use(ensureHttps) // Because authenticate is based on public, any call // using this stack will also be passed ctx instead // of the background context for handlers in the stack. authenticate := public.Use(authenticate, ensureAdmin) http.Handle("/admin", authenticate.HandleFunc(admin)) http.Handle("/", public.HandleFunc(index)) http.ListenAndServe(":8080", nil) } func makeNewContext(ctx context.Context) context.Context { // Just an example of setting up a context, you should // avoid using strings for keys in context.WithValue ctx = context.WithValue(ctx, "some-key", "some-value") return ctx }
Output:
func (*Stack) Handle ¶
Handle creates a http.Handler from a stack of middleware functions and a httpctx.Handler.
func (*Stack) HandleFunc ¶
func (s *Stack) HandleFunc(f func(context.Context, http.ResponseWriter, *http.Request) error) http.Handler
HandleFunc returns a http.Handler (compatible with the standard library http package), which calls the middleware handlers in the stack s, followed by the handler function f.