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

Side by Side 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 unified diff | Download patch
« no previous file with comments | « no previous file | server/router/router.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The LUCI Authors. All rights reserved. 1 // Copyright 2015 The LUCI Authors. All rights reserved.
2 // Use of this source code is governed under the Apache License, Version 2.0 2 // Use of this source code is governed under the Apache License, Version 2.0
3 // that can be found in the LICENSE file. 3 // that can be found in the LICENSE file.
4 4
5 // Package middleware defines base type for context-aware HTTP request handler. 5 // Package middleware defines base type for context-aware HTTP request handler.
6 // See appengine/middleware for examples of how to use it in GAE environment. 6 // See appengine/middleware for examples of how to use it in GAE environment.
7 package middleware 7 package middleware
8 8
9 import ( 9 import (
10 "net/http" 10 "net/http"
11 11
12 "github.com/julienschmidt/httprouter" 12 "github.com/julienschmidt/httprouter"
13 "golang.org/x/net/context" 13 "golang.org/x/net/context"
14 ) 14 )
15 15
16 // Handler is the type for all request handlers. Of particular note, it's the 16 // Handler is the type for all request handlers. Of particular note, it's the
17 // same as httprouter.Handle, except that it also has a context parameter. 17 // same as httprouter.Handle, except that it also has a context parameter.
18 type Handler func(context.Context, http.ResponseWriter, *http.Request, httproute r.Params) 18 type Handler func(context.Context, http.ResponseWriter, *http.Request, httproute r.Params)
19 19
20 // ChainedHandler is the same as Handler, except that it includes a Handler
21 // parameter that calls the next ChainedHandler in the middleware chain when inv oked.
22 type ChainedHandler func(context.Context, http.ResponseWriter, *http.Request, ht tprouter.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
23
20 // Middleware takes a handler, wraps it with some additional logic, and returns 24 // Middleware takes a handler, wraps it with some additional logic, and returns
21 // resulting handler. 25 // resulting handler.
22 type Middleware func(Handler) Handler 26 type Middleware func(Handler) Handler
23 27
24 // Base is a start of the middlware chain. It sets up initial context with all 28 // Chain contains a Handler and a pointer to the next element in the Chain.
29 type Chain struct {
30 » Handler ChainedHandler
31 » next *Chain
32 }
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
33
34 // Handle calls the chain's Handler function after adding necessary arguments.
35 func (c *Chain) Handle(ctx context.Context, wr http.ResponseWriter, r *http.Requ est, p httprouter.Params) {
36 » if c.next != nil {
37 » » c.Handler(ctx, wr, r, p, c.next.Handle)
38 » }
39 }
40
41 // Append adds chains to an existing chain and returns the result.
42 func (c Chain) Append(chains ...Chain) Chain {
43 » if len(chains) == 0 {
44 » » return c
45 » }
46 » // TODO(nishanths): Hold a private reference to the tail *Chain in the
47 » // Chain struct to eliminate this loop.
48 » for ; c.next != nil; c = *c.next {
49 » }
50 » c.next = &chains[0]
51 » return chains[0].Append(chains[1:]...)
52 }
53
54 // AppendHandlers adds a list of ChainedHandlers to a Chain.
55 func (c Chain) AppendHandlers(handlers ...ChainedHandler) Chain {
56 » chain := NewChain(handlers...)
57 » return c.Append(chain)
58 }
59
60 // NewChain creates a Chain from ChainedHandler list.
61 func NewChain(handlers ...ChainedHandler) Chain {
62 » if len(handlers) == 0 {
63 » » return Chain{handlers[0], nil}
64 » }
65 » next := NewChain(handlers[1:]...)
66 » return Chain{handlers[0], &next}
67 }
68
69 // Base is a start of the middleware chain. It sets up initial context with all
25 // base services and passes it to the given handler. Return value of Base can 70 // base services and passes it to the given handler. Return value of Base can
26 // be plugged in into httprouter directly. 71 // be plugged in into httprouter directly.
27 type Base func(Handler) httprouter.Handle 72 type Base func(Handler) httprouter.Handle
28 73
29 // TestingBase is Base that passes given context to the handler. Useful in 74 // TestingBase is Base that passes given context to the handler. Useful in
30 // tests. 75 // tests.
31 func TestingBase(c context.Context) Base { 76 func TestingBase(c context.Context) Base {
32 return func(h Handler) httprouter.Handle { 77 return func(h Handler) httprouter.Handle {
33 return func(rw http.ResponseWriter, r *http.Request, p httproute r.Params) { 78 return func(rw http.ResponseWriter, r *http.Request, p httproute r.Params) {
34 h(c, rw, r, p) 79 h(c, rw, r, p)
35 } 80 }
36 } 81 }
37 } 82 }
38 83
39 // WithContextValue is a middleware that adds a value to the context before 84 // WithContextValue is a middleware that adds a value to the context before
40 // calling the handler. 85 // calling the handler.
41 func WithContextValue(h Handler, key, val interface{}) Handler { 86 func WithContextValue(h Handler, key, val interface{}) Handler {
42 return func(c context.Context, rw http.ResponseWriter, r *http.Request, p httprouter.Params) { 87 return func(c context.Context, rw http.ResponseWriter, r *http.Request, p httprouter.Params) {
43 h(context.WithValue(c, key, val), rw, r, p) 88 h(context.WithValue(c, key, val), rw, r, p)
44 } 89 }
45 } 90 }
OLDNEW
« 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