Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(711)

Unified Diff: server/middleware/middleware.go

Issue 2043423004: Make HTTP middleware easier to use (Closed) Base URL: https://github.com/luci/luci-go@master
Patch Set: Fixes to middleware append related functions, docs Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | server/router/router.go » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
« no previous file with comments | « no previous file | server/router/router.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698