Chromium Code Reviews| Index: server/middleware/middleware.go |
| diff --git a/server/middleware/middleware.go b/server/middleware/middleware.go |
| index 81dd71920964a7089cb8e6de99999f9bc331b652..3593819b375a4e7f0c66982a980eed7141fc2437 100644 |
| --- a/server/middleware/middleware.go |
| +++ b/server/middleware/middleware.go |
| @@ -17,11 +17,56 @@ 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) |
|
iannucci
2016/06/09 21:30:08
Since we have all the middleware in this repo, it
Vadim Sh.
2016/06/09 21:45:12
+1
Having both Handler and ChainedHandler is conf
nishanths
2016/06/13 17:30:44
I like this too. I've changed the router package t
|
| + |
| // 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 |
| +} |
|
iannucci
2016/06/09 21:30:08
Why not just a []Handler? I think it could simplif
Vadim Sh.
2016/06/09 21:45:12
+1
since chains are append-only, it is even fine
nishanths
2016/06/13 17:30:44
Good point. The API primariy now uses router.Handl
|
| + |
| +// 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) { |
| + if c.next != nil { |
| + c.Handler(ctx, wr, r, p, c.next.Handle) |
| + } |
| +} |
| + |
| +// Append adds chains to an existing chain and returns the result. |
| +func (c Chain) Append(chains ...Chain) Chain { |
| + if len(chains) == 0 { |
| + return c |
| + } |
| + // 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] |
| + return chains[0].Append(chains[1:]...) |
| +} |
| + |
| +// AppendHandlers adds a list of ChainedHandlers to a Chain. |
| +func (c Chain) AppendHandlers(handlers ...ChainedHandler) Chain { |
| + chain := NewChain(handlers...) |
| + return c.Append(chain) |
| +} |
| + |
| +// NewChain creates a Chain from ChainedHandler list. |
| +func NewChain(handlers ...ChainedHandler) Chain { |
| + if len(handlers) == 0 { |
| + return Chain{handlers[0], nil} |
| + } |
| + next := NewChain(handlers[1:]...) |
| + return Chain{handlers[0], &next} |
| +} |
| + |
| +// 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 |