Chromium Code Reviews| Index: server/middleware/middleware.go |
| diff --git a/server/middleware/middleware.go b/server/middleware/middleware.go |
| index 81dd71920964a7089cb8e6de99999f9bc331b652..707229f105d49e4fdf80d4c1ca2b99d19c055a69 100644 |
| --- a/server/middleware/middleware.go |
| +++ b/server/middleware/middleware.go |
| @@ -17,11 +17,63 @@ import ( |
| // same as httprouter.Handle, except that it also has a context parameter. |
| type Handler func(context.Context, http.ResponseWriter, *http.Request, httprouter.Params) |
| +// ChainedHandler is the same as Handler, except that it includes a Handler |
| +// parameter that calls the next ChainedHandler in the middleware chain when invoked. |
| +type ChainedHandler func(context.Context, http.ResponseWriter, *http.Request, httprouter.Params, Handler) |
|
nishanths
2016/06/09 04:23:47
ChainedHandler can eventually be renamed to Handle
|
| + |
| // Middleware takes a handler, wraps it with some additional logic, and returns |
| // resulting handler. |
| type Middleware func(Handler) Handler |
| -// Base is a start of the middlware chain. It sets up initial context with all |
| +// Chain contains a Handler and a pointer to the next element in the Chain. |
| +type Chain struct { |
| + Handler ChainedHandler |
| + next *Chain |
| +} |
| + |
| +// Handle calls the chain's Handler function after adding necessary arguments. |
| +func (c *Chain) Handle(ctx context.Context, wr http.ResponseWriter, r *http.Request, p httprouter.Params) { |
| + c.Handler(ctx, wr, r, p, c.next.Handle) |
| +} |
| + |
| +// Add adds chains to an existing chain. |
| +func (c *Chain) Add(chains ...Chain) { |
| + if len(chains) == 0 { |
| + return |
| + } |
| + // TODO(nishanths): Hold a private reference to the tail *Chain in the |
| + // Chain struct to eliminate this loop. |
| + for ; c.next != nil; c = c.next { |
| + } |
| + c.next = &chains[0] |
| + chains[0].Add(chains[1:]...) |
| +} |
| + |
| +// AddHandlers adds a list of ChainedHandlers to a Chain. |
| +func (c *Chain) AddHandlers(handlers ...ChainedHandler) { |
| + chain := NewChain(handlers...) |
| + c.Add(chain) |
| +} |
| + |
| +// NewChain creates a Chain from ChainedHandler list. |
| +func NewChain(handlers ...ChainedHandler) Chain { |
| + if len(handlers) == 0 { |
| + return voidChain() |
| + } |
| + next := NewChain(handlers[1:]...) |
| + return Chain{handlers[0], &next} |
| +} |
| + |
| +// voidChain returns a Chain that has no Chain after it (that is, it's next |
| +// field is nil). |
| +func voidChain() Chain { |
| + return Chain{ |
| + ChainedHandler(func(c context.Context, rw http.ResponseWriter, r *http.Request, p httprouter.Params, next Handler) {}), |
| + nil, |
| + } |
| +} |
| + |
| +// Base is a start of the middleware chain. It sets up initial context with all |
| // base services and passes it to the given handler. Return value of Base can |
| // be plugged in into httprouter directly. |
| type Base func(Handler) httprouter.Handle |