Documentation ¶
Overview ¶
Package qctx is a light-weight, type-safe, per-http-request state manager, with simple middleware stacking and a few middleware and helper functions.
Request-scoped data is kept in a Ctx struct, which is passed as an argument to handlers and middleware. Package qctx defines its own signature for Middleware functions, but middleware written to the standard library http.Handler interface can be included via a wrapper. See MwStripPrefix for an example of this.
Support is included for net/http, julienschmidt/httprouter and github.com/gkong/go-qweb/qsess.
User data can flow through middleware and handlers in several ways: (1) struct Ctx contains a qsess.Session, which (if you choose to use qsess) can store user data for the duration of a session, (2) you can fork this package and add your own members to struct Ctx - an easy and type-safe way to share data for the duration of a request (if you fork, the code is organized to make it very easy to remove the dependencies on httprouter and qsess, thus making qctx a zero-dependency package), and (3) struct Ctx contains an http.Request, which (in go 1.7 or later) contains a Context, which can store request-scoped user data, enabling intermixture of third-party middleware that uses http.Request.WithContext and http.Request.Context (through the use of a simple wrapper).
Handler:
func myHandler(c *qctx.Ctx) { fmt.Fprint(c.W, "Hello, world!") }
Middleware:
func myMiddleware(next CtxHandler) CtxHandler { return CtxHandlerFunc(func(c *Ctx) { // do stuff before calling downstream next.CtxServeHTTP(c) // do stuff after returning from downstream }) }
Middleware Stacking:
mw := qctx.MwStack(qctx.MwRecovery(os.Stderr), qctx.MwLogger(os.Stderr, true)) mw = mw.Append(myMiddleware)
Use with net/http:
http.Handle("/hello", mw.Handle(myHandler)))
Use with julienschmidt/httprouter:
r := httprouter.New() r.GET("/hello", mw.HRHandle(myHandler)))
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func H2Ctx ¶
func H2Ctx(next CtxHandler) http.Handler
H2Ctx adapts a CtxHandler to be callable by net/http.
func Hr2Ctx ¶
func Hr2Ctx(next CtxHandler) httprouter.Handle
Hr2Ctx adapts a CtxHandler to be callable by julienschmidt/httprouter.
Types ¶
type Ctx ¶
type Ctx struct { W http.ResponseWriter R *http.Request // the following are optional and can be eliminated if customizing Ctx Params httprouter.Params // only used if using julienschmidt/httprouter Sess *qsess.Session // only used if using github.com/gkong/go-qweb/qsess }
Ctx holds per-request ("context") information. To add your own data, fork this code and add members to the Ctx struct.
func (*Ctx) ReadJSON ¶
func (c *Ctx) ReadJSON(dest json.Unmarshaler) bool
ReadJSON unmarshals JSON from the request body into the object referenced by dest, which must have a deserializer, which can be hand-written or generated by ffjson or a similar tool. If it fails, it calls http.Error() and returns false.
type CtxHandler ¶
type CtxHandler interface {
CtxServeHTTP(*Ctx)
}
CtxHandler is a handler/middleware interface like http.Handler, but with a single ctx argument.
type CtxHandlerFunc ¶
type CtxHandlerFunc func(*Ctx)
func (CtxHandlerFunc) CtxServeHTTP ¶
func (f CtxHandlerFunc) CtxServeHTTP(c *Ctx)
type MakerStack ¶
type MakerStack []MwMaker
func MwStack ¶
func MwStack(makers ...MwMaker) MakerStack
MwStack makes a middleware stack from one or more MwMakers.
func (MakerStack) Append ¶
func (s MakerStack) Append(makers ...MwMaker) MakerStack
Append returns a new MakerStack, composed of the contents of an existing MakerStack and some additional MwMakers. It does not modify the existing MakerStack.
func (MakerStack) HRHandle ¶
func (s MakerStack) HRHandle(f func(*Ctx)) httprouter.Handle
HRHandle combines a middleware stack and a final handler function into an httprouter.Handle, ready to be registered with julienschmidt/httprouter.
type MwMaker ¶
type MwMaker func(next CtxHandler) CtxHandler
MwMaker defines a piece of stackable middleware. Given a function to be called next, it returns a handler function, which performs a middleware task and calls the next function, which it remembers by closing over the MwMaker's "next" parameter.
func MwHeader ¶
MwHeader is middleware which sets HTTP response headers. Pass it one or more key/value pairs.
func MwLogger ¶
MwLogger is middleware which logs HTTP requests to a given io.Writer, optionally including decoration with ANSI escape sequences.
It wraps http.ResponseWriter, to capture the response status code, so it should be placed upstream of any middleware that could generate a status code.
func MwRecovery ¶
MwRecovery is panic-recovery middleware in the spirit of http.Error() - it assumes the client, upon receipt of an error code, expects a plain-text error message in the response body. If it is unable to reply in that manner, because the status code has already been set, or some data has already been written to the response body, it panics again, which results in the client seeing a dropped connection (which is better than a false indication of success or an incomprehensible error message).
func MwRequireSess ¶
MwRequireSess is middleware which checks for a valid qsess session. If it finds one, it calls downstream, otherwise, it returns an error. It also refreshes session expiration time, if needed.
func MwStripPrefix ¶
MwStripPrefix is middleware that removes a given prefix from the request URL's path, by wrapping the standard go library http.StripPrefix. It is an example of how to incorporate http.Handler style middleware into a stack of CtxHandlers.
type WrappedRW ¶
type WrappedRW struct { http.ResponseWriter WroteHeader bool // headers and code written, can no longer be changed WroteBody bool // have written data to the response body StatusCode int // http status code, only meaningful if wroteHeader true }
WrappedRW wraps http.ResponseWriter, to capture the HTTP status code and observe whether or not any data has been written to the response body.