| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2016 The LUCI Authors. All rights reserved. |
| 2 // Use of this source code is governed under the Apache License, Version 2.0 |
| 3 // that can be found in the LICENSE file. |
| 4 |
| 5 /* |
| 6 Package router provides a HTTP router with support for middleware and groups. |
| 7 It wraps around julienschmidt/httprouter. |
| 8 |
| 9 Usage: |
| 10 |
| 11 r := router.Default() |
| 12 r.UseHandlers(Logger()) |
| 13 r.GET("/", middleware.NewChain(RootSpecificMiddleware(), rootHandler)) /
/ Executes Logger, RootSpecificMiddleware, rootHandler in order |
| 14 |
| 15 authorized := r.Group("authorized") |
| 16 authorized.UseHandlers(Authenticator(), FooAuthMiddleware()) |
| 17 authorized.DELETE("/comment/:id", commentDeleteHandler) // Executes Logg
er, Authenticator, FooAuthMiddleware, commentDeleteHandler in order (path: /auth
orized/comment/:id) |
| 18 |
| 19 func rootHandler(ctx context.Context, rw http.ResponseWriter, r *http.Re
quest, p httprouter.Params, _ middleware.Handler) { |
| 20 io.WriteString(rw, "hello from the root route") |
| 21 } |
| 22 |
| 23 func Logger() middleware.ChainedHandler { |
| 24 return func(ctx context.Context, rw http.ResponseWriter, r *http
.Request, p httprouter.Params, next middleware.Handler) { |
| 25 log.Println("log before") |
| 26 next(ctx, rw, r, p) |
| 27 log.Println("log after") |
| 28 } |
| 29 } |
| 30 */ |
| 31 package router |
| 32 |
| 33 import ( |
| 34 "net/http" |
| 35 |
| 36 "github.com/julienschmidt/httprouter" |
| 37 "github.com/luci/luci-go/server/middleware" |
| 38 "golang.org/x/net/context" |
| 39 ) |
| 40 |
| 41 // Router represents the main router type. |
| 42 type Router struct { |
| 43 hrouter *httprouter.Router |
| 44 context context.Context |
| 45 handlers middleware.Chain |
| 46 basePath string |
| 47 parent *Router |
| 48 root bool |
| 49 } |
| 50 |
| 51 var _ http.Handler = Default() |
| 52 |
| 53 // Default creates a Router with context.Background() as initial context. |
| 54 func Default() *Router { |
| 55 return New(context.Background()) |
| 56 } |
| 57 |
| 58 // New creates a Router with specified initial context. |
| 59 func New(ctx context.Context) *Router { |
| 60 r := &Router{ |
| 61 hrouter: httprouter.New(), |
| 62 context: ctx, |
| 63 basePath: "/", |
| 64 parent: nil, |
| 65 root: true, |
| 66 } |
| 67 return r |
| 68 } |
| 69 |
| 70 // UseHandlers adds handlers as middleware to the group. The added middleware ap
plies to |
| 71 // all routes in the current group and in groups derived from the current group. |
| 72 func (r *Router) UseHandlers(handlers ...middleware.ChainedHandler) { |
| 73 r.handlers = r.handlers.Append(middleware.NewChain(handlers...)) |
| 74 } |
| 75 |
| 76 // Use adds middleware chains to the group. The added middleware applies to |
| 77 // all routes in the current group and in groups derived from the current group. |
| 78 func (r *Router) Use(chains ...middleware.Chain) { |
| 79 r.handlers = r.handlers.Append(chains...) |
| 80 } |
| 81 |
| 82 // Group creates a new router with an updated base path. |
| 83 // The new router carries over configuration from the router it derives |
| 84 // from. |
| 85 func (r *Router) Group(relativePath string) *Router { |
| 86 return &Router{ |
| 87 hrouter: r.hrouter, |
| 88 context: r.context, |
| 89 handlers: r.handlers, |
| 90 basePath: r.basePath + relativePath, |
| 91 parent: r, |
| 92 root: false, |
| 93 } |
| 94 } |
| 95 |
| 96 // adapt converts a middleware.Chain to a httrouter.Handle with |
| 97 // initial context. |
| 98 func (r *Router) adapt(chain middleware.Chain) httprouter.Handle { |
| 99 return httprouter.Handle(func(rw http.ResponseWriter, req *http.Request,
p httprouter.Params) { |
| 100 chain.Handle(r.context, rw, req, p) |
| 101 }) |
| 102 } |
| 103 |
| 104 // GET is a shortcut for router.Handle("GET", path, handlers) |
| 105 func (r *Router) GET(path string, handlers middleware.Chain) { |
| 106 r.Handle("GET", path, handlers) |
| 107 } |
| 108 |
| 109 // HEAD is a shortcut for router.Handle("HEAD", path, handlers) |
| 110 func (r *Router) HEAD(path string, handlers middleware.Chain) { |
| 111 r.Handle("HEAD", path, handlers) |
| 112 } |
| 113 |
| 114 // OPTIONS is a shortcut for router.Handle("OPTIONS", path, handlers) |
| 115 func (r *Router) OPTIONS(path string, handlers middleware.Chain) { |
| 116 r.Handle("OPTIONS", path, handlers) |
| 117 } |
| 118 |
| 119 // POST is a shortcut for router.Handle("POST", path, handlers) |
| 120 func (r *Router) POST(path string, handlers middleware.Chain) { |
| 121 r.Handle("POST", path, handlers) |
| 122 } |
| 123 |
| 124 // PUT is a shortcut for router.Handle("PUT", path, handlers) |
| 125 func (r *Router) PUT(path string, handlers middleware.Chain) { |
| 126 r.Handle("PUT", path, handlers) |
| 127 } |
| 128 |
| 129 // PATCH is a shortcut for router.Handle("PATCH", path, handlers) |
| 130 func (r *Router) PATCH(path string, handlers middleware.Chain) { |
| 131 r.Handle("PATCH", path, handlers) |
| 132 } |
| 133 |
| 134 // DELETE is a shortcut for router.Handle("DELETE", path, handlers) |
| 135 func (r *Router) DELETE(path string, handlers middleware.Chain) { |
| 136 r.Handle("DELETE", path, handlers) |
| 137 } |
| 138 |
| 139 // Handle registers a new middleware chain-style handler with the given method |
| 140 // and path. |
| 141 func (r *Router) Handle(method, path string, handlers middleware.Chain) { |
| 142 mergedHandlers := r.handlers.Append(handlers) |
| 143 h := r.adapt(mergedHandlers) |
| 144 r.hrouter.Handle(method, path, h) |
| 145 } |
| 146 |
| 147 // ServeHTTP makes Router implement the http.Handler interface. |
| 148 func (r *Router) ServeHTTP(rw http.ResponseWriter, req *http.Request) { |
| 149 r.hrouter.ServeHTTP(rw, req) |
| 150 } |
| 151 |
| 152 // TODO(nishanths): implement Handler, HandlerFunc adapter methods on *Router |
| OLD | NEW |