apollo

package module
v0.0.0-...-16b4206 Latest Latest
Warning

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

Go to latest
Published: Jan 4, 2017 License: MIT Imports: 2 Imported by: 10

README

This repository has been transferred to https://github.com/thisendout/apollo. This fork will remain to preserve go imports but will not receive any updates

Apollo

GoDoc

Apollo is a middleware-chaining helper for Golang web applications using google's net/context package. Apollo is a fork of Alice, modified to support passing the ctx context.Context param through middleware and HTTP handlers.

Apollo is meant to chain handler functions with this signature:

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

Relevant and influential articles:

Usage

apollo.New(Middleware1, Middlware2, Middleware3).With(ctx).Then(App)

Integration with http.Handler middleware

Apollo provides a Wrap function to inject normal http.Handler-based middleware into the chain. The context will skip over the injected middleware and pass unharmed to the next context-aware handler in the chain.

apollo.New(ContextMW1, apollo.Wrap(NormalMiddlware), ContextMW2).With(ctx).Then(App)

Motivation

Given a handler:

func HandlerOne(w http.ResponseWriter, r *http.Request) {}

We can serve it using the following:

http.HandleFunc("/one", HandlerOne)
// or http.Handle("/one", http.HandlerFunc(HandlerOne))

However, given a handler that expects a net/context:

func HandlerAlpha(ctx context.Context, w http.ResponseWriter, r *http.Request) {}

We would need to create a wrapper along the lines of:

func withContext(ctx context.Context, fn func(context.Context, http.ResponseWriter, *http.Request)) http.HandlerFunc {
  return func(w http.ResponseWriter, r *http.Request) {
    fn(ctx, w, r)
  }
}

and serve with:

ctx := context.Background()
http.Handle("/alpha", withContext(ctx, HandlerAlpha))

With this pattern, we can build nested middleware/handler calls that can be used with any net/http compatible router/mux. However, we can't use Alice for chaining because we no longer conform to the http.Handler interface that Alice expects.

Apollo enables Alice-style chaining of context-aware middleware and handlers.

Documentation

Overview

Apollo provides `net/context`-aware middleware chaining

Apollo provides `net/context`-aware middleware chaining

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Chain

type Chain struct {
	// contains filtered or unexported fields
}

Chain acts as a list of apollo.Handler constructors. Chain is effectively immutable: once created, it will always hold the same set of constructors in the same order. Chain also holds a copy of the context to be injected to the first middleware when .Then() is called.

func New

func New(constructors ...Constructor) Chain

New creates a new chain, memorizing the given list of middleware constructors. New serves no other function, constructors are only called upon a call to Then().

func (Chain) Append

func (c Chain) Append(constructors ...Constructor) Chain

Append extends a chain, adding the specified constructors as the last ones in the request flow.

Append returns a new chain, leaving the original one untouched.

stdChain := alice.New(m1, m2)
extChain := stdChain.Append(m3, m4)
// requests in stdChain go m1 -> m2
// requests in extChain go m1 -> m2 -> m3 -> m4

func (Chain) Then

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

Then chains the middleware and returns the final Handler.

New(m1, m2, m3).Then(h)

is equivalent to:

m1(m2(m3(h)))

When the request comes in, it will be passed to m1, then m2, then m3 and finally, the given handler (assuming every middleware calls the following one).

A chain can be safely reused by calling Then() several times.

stdStack := alice.New(ratelimitHandler, csrfHandler)
indexPipe = stdStack.Then(indexHandler)
authPipe = stdStack.Then(authHandler)

Note that constructors are called on every call to Then() and thus several instances of the same middleware will be created when a chain is reused in this way. For proper middleware, this should cause no problems.

Then() treats nil as http.DefaultServeMux.

func (Chain) ThenFunc

func (c Chain) ThenFunc(fn HandlerFunc) http.Handler

ThenFunc works identically to Then, but takes a HandlerFunc instead of a Handler.

The following two statements are equivalent:

c.Then(http.HandlerFunc(fn))
c.ThenFunc(fn)

ThenFunc provides all the guarantees of Then.

func (Chain) With

func (c Chain) With(ctx context.Context) Chain

With sets the context to be passed to the start of the Chain.

The final handler will use the modified context that has passed through the middleware chain.

type Constructor

type Constructor func(Handler) Handler

A constructor for a piece of context-aware middleware.

func Wrap

func Wrap(h func(http.Handler) http.Handler) Constructor

Wrap allows injection of normal http.Handler middleware into an apollo middleware chain The context will be preserved and passed through intact

type Handler

type Handler interface {
	ServeHTTP(context.Context, http.ResponseWriter, *http.Request)
}

Handler is a context-aware interface analagous to the `net/http` http.Handler interface The only difference is that a context.Context is required as the first parameter in ServeHTTP.

type HandlerFunc

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

HandlerFunc, similar to http.HandlerFunc, is an adapter to convert ordinary functions into handlers.

func (HandlerFunc) ServeHTTP

func (h HandlerFunc) ServeHTTP(ctx context.Context, w http.ResponseWriter, r *http.Request)

ServeHTTP calls the wrapped function h(ctx, w, r)

Jump to

Keyboard shortcuts

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