Context-aware middleware chains for golang web applications
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
.travis.yml
LICENSE
README.md
apollo.go
apollo_test.go
chain.go
chain_test.go
fixtures_test.go

README.md

Apollo

GoDoc Build Status

Apollo is a middleware-chaining helper for Golang web applications using the stdlib 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)

Changelog

  • v2.0.0 - Pending

  • Updated to use stdlib context in go 1.7+. Use v1.0.0 for projects utilizing golang.org/x/net/context.

  • Repository transferred from cyclopsci/apollo, which is now a fork of this repo.

  • v1.0.0

  • Initial release with chaining for golang.org/x/net/context

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.

Reference

Relevant and influential articles: