| 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
|
|
|