qctx

package
v0.0.2 Latest Latest
Warning

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

Go to latest
Published: Aug 11, 2021 License: MIT Imports: 9 Imported by: 1

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

func (c *Ctx) Error(s string, code int)

Error is a simple wrapper for http.Error.

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.

func (*Ctx) WriteJSON

func (c *Ctx) WriteJSON(src json.Marshaler)

WriteJSON marshals JSON from the object referenced by src into the request body. src must have a deserializer, which can be hand-written or generated by ffjson or a similar tool. If it fails, it calls http.Error().

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.

func (MakerStack) Handle

func (s MakerStack) Handle(f func(*Ctx)) http.Handler

Handle combines a middleware stack and a final handler function into an http.Handler, ready to be registered with net/http.

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

func MwHeader(s ...string) MwMaker

MwHeader is middleware which sets HTTP response headers. Pass it one or more key/value pairs.

func MwLogger

func MwLogger(log io.Writer, useAnsiColor bool) MwMaker

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

func MwRecovery(log io.Writer, printStack bool, printAll bool) MwMaker

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

func MwRequireSess(st *qsess.Store) MwMaker

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

func MwStripPrefix(prefix string) MwMaker

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.

func (*WrappedRW) Write

func (w *WrappedRW) Write(data []byte) (int, error)

func (*WrappedRW) WriteHeader

func (w *WrappedRW) WriteHeader(code int)

Jump to

Keyboard shortcuts

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