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

Unified Diff: server/router/router.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
« server/middleware/middleware.go ('K') | « server/middleware/middleware.go ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: server/router/router.go
diff --git a/server/router/router.go b/server/router/router.go
new file mode 100644
index 0000000000000000000000000000000000000000..3f651f67b104782793b3d2776403fd4896a79c29
--- /dev/null
+++ b/server/router/router.go
@@ -0,0 +1,152 @@
+// Copyright 2016 The LUCI Authors. All rights reserved.
+// Use of this source code is governed under the Apache License, Version 2.0
+// that can be found in the LICENSE file.
+
+/*
+Package router provides a HTTP router with support for middleware and groups.
+It wraps around julienschmidt/httprouter.
+
+Usage:
+
+ r := router.Default()
+ r.UseHandlers(Logger())
+ r.GET("/", middleware.NewChain(RootSpecificMiddleware(), rootHandler)) // Executes Logger, RootSpecificMiddleware, rootHandler in order
+
+ authorized := r.Group("authorized")
+ authorized.UseHandlers(Authenticator(), FooAuthMiddleware())
+ authorized.DELETE("/comment/:id", commentDeleteHandler) // Executes Logger, Authenticator, FooAuthMiddleware, commentDeleteHandler in order (path: /authorized/comment/:id)
+
+ func rootHandler(ctx context.Context, rw http.ResponseWriter, r *http.Request, p httprouter.Params, _ middleware.Handler) {
+ io.WriteString(rw, "hello from the root route")
+ }
+
+ func Logger() middleware.ChainedHandler {
+ return func(ctx context.Context, rw http.ResponseWriter, r *http.Request, p httprouter.Params, next middleware.Handler) {
+ log.Println("log before")
+ next(ctx, rw, r, p)
+ log.Println("log after")
+ }
+ }
+*/
+package router
+
+import (
+ "net/http"
+
+ "github.com/julienschmidt/httprouter"
+ "github.com/luci/luci-go/server/middleware"
+ "golang.org/x/net/context"
+)
+
+// Router represents the main router type.
+type Router struct {
+ hrouter *httprouter.Router
+ context context.Context
+ handlers middleware.Chain
+ basePath string
+ parent *Router
+ root bool
+}
+
+var _ http.Handler = Default()
+
+// Default creates a Router with context.Background() as initial context.
+func Default() *Router {
+ return New(context.Background())
+}
+
+// New creates a Router with specified initial context.
+func New(ctx context.Context) *Router {
+ r := &Router{
+ hrouter: httprouter.New(),
+ context: ctx,
+ basePath: "/",
+ parent: nil,
+ root: true,
+ }
+ return r
+}
+
+// UseHandlers adds handlers as middleware to the group. The added middleware applies to
+// all routes in the current group and in groups derived from the current group.
+func (r *Router) UseHandlers(handlers ...middleware.ChainedHandler) {
+ r.handlers = r.handlers.Append(middleware.NewChain(handlers...))
+}
+
+// Use adds middleware chains to the group. The added middleware applies to
+// all routes in the current group and in groups derived from the current group.
+func (r *Router) Use(chains ...middleware.Chain) {
+ r.handlers = r.handlers.Append(chains...)
+}
+
+// Group creates a new router with an updated base path.
+// The new router carries over configuration from the router it derives
+// from.
+func (r *Router) Group(relativePath string) *Router {
+ return &Router{
+ hrouter: r.hrouter,
+ context: r.context,
+ handlers: r.handlers,
+ basePath: r.basePath + relativePath,
+ parent: r,
+ root: false,
+ }
+}
+
+// adapt converts a middleware.Chain to a httrouter.Handle with
+// initial context.
+func (r *Router) adapt(chain middleware.Chain) httprouter.Handle {
+ return httprouter.Handle(func(rw http.ResponseWriter, req *http.Request, p httprouter.Params) {
+ chain.Handle(r.context, rw, req, p)
+ })
+}
+
+// GET is a shortcut for router.Handle("GET", path, handlers)
+func (r *Router) GET(path string, handlers middleware.Chain) {
+ r.Handle("GET", path, handlers)
+}
+
+// HEAD is a shortcut for router.Handle("HEAD", path, handlers)
+func (r *Router) HEAD(path string, handlers middleware.Chain) {
+ r.Handle("HEAD", path, handlers)
+}
+
+// OPTIONS is a shortcut for router.Handle("OPTIONS", path, handlers)
+func (r *Router) OPTIONS(path string, handlers middleware.Chain) {
+ r.Handle("OPTIONS", path, handlers)
+}
+
+// POST is a shortcut for router.Handle("POST", path, handlers)
+func (r *Router) POST(path string, handlers middleware.Chain) {
+ r.Handle("POST", path, handlers)
+}
+
+// PUT is a shortcut for router.Handle("PUT", path, handlers)
+func (r *Router) PUT(path string, handlers middleware.Chain) {
+ r.Handle("PUT", path, handlers)
+}
+
+// PATCH is a shortcut for router.Handle("PATCH", path, handlers)
+func (r *Router) PATCH(path string, handlers middleware.Chain) {
+ r.Handle("PATCH", path, handlers)
+}
+
+// DELETE is a shortcut for router.Handle("DELETE", path, handlers)
+func (r *Router) DELETE(path string, handlers middleware.Chain) {
+ r.Handle("DELETE", path, handlers)
+}
+
+// Handle registers a new middleware chain-style handler with the given method
+// and path.
+func (r *Router) Handle(method, path string, handlers middleware.Chain) {
+ mergedHandlers := r.handlers.Append(handlers)
+ h := r.adapt(mergedHandlers)
+ r.hrouter.Handle(method, path, h)
+}
+
+// ServeHTTP makes Router implement the http.Handler interface.
+func (r *Router) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
+ r.hrouter.ServeHTTP(rw, req)
+}
+
+// TODO(nishanths): implement Handler, HandlerFunc adapter methods on *Router
« server/middleware/middleware.go ('K') | « server/middleware/middleware.go ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698