github.com/jasonish/buffalo@v0.8.2-0.20170413145823-bacbdd415f1b/router.go (about)

     1  package buffalo
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"path"
     7  	"reflect"
     8  	"sort"
     9  	//"strings"
    10  
    11  	"github.com/markbates/inflect"
    12  )
    13  
    14  // GET maps an HTTP "GET" request to the path and the specified handler.
    15  func (a *App) GET(p string, h Handler) RouteInfo {
    16  	return a.addRoute("GET", p, h)
    17  }
    18  
    19  // POST maps an HTTP "POST" request to the path and the specified handler.
    20  func (a *App) POST(p string, h Handler) RouteInfo {
    21  	return a.addRoute("POST", p, h)
    22  }
    23  
    24  // PUT maps an HTTP "PUT" request to the path and the specified handler.
    25  func (a *App) PUT(p string, h Handler) RouteInfo {
    26  	return a.addRoute("PUT", p, h)
    27  }
    28  
    29  // DELETE maps an HTTP "DELETE" request to the path and the specified handler.
    30  func (a *App) DELETE(p string, h Handler) RouteInfo {
    31  	return a.addRoute("DELETE", p, h)
    32  }
    33  
    34  // HEAD maps an HTTP "HEAD" request to the path and the specified handler.
    35  func (a *App) HEAD(p string, h Handler) RouteInfo {
    36  	return a.addRoute("HEAD", p, h)
    37  }
    38  
    39  // OPTIONS maps an HTTP "OPTIONS" request to the path and the specified handler.
    40  func (a *App) OPTIONS(p string, h Handler) RouteInfo {
    41  	return a.addRoute("OPTIONS", p, h)
    42  }
    43  
    44  // PATCH maps an HTTP "PATCH" request to the path and the specified handler.
    45  func (a *App) PATCH(p string, h Handler) RouteInfo {
    46  	return a.addRoute("PATCH", p, h)
    47  }
    48  
    49  // Redirect from one URL to another URL. Only works for "GET" requests.
    50  func (a *App) Redirect(status int, from, to string) RouteInfo {
    51  	return a.GET(from, func(c Context) error {
    52  		return c.Redirect(status, to)
    53  	})
    54  }
    55  
    56  // ServeFiles maps an path to a directory on disk to serve static files.
    57  // Useful for JavaScript, images, CSS, etc...
    58  /*
    59  	a.ServeFiles("/assets", http.Dir("path/to/assets"))
    60  */
    61  func (a *App) ServeFiles(p string, root http.FileSystem) {
    62  	a.router.PathPrefix(p).Handler(http.StripPrefix(p, http.FileServer(root)))
    63  }
    64  
    65  // Resource maps an implementation of the Resource interface
    66  // to the appropriate RESTful mappings. Resource returns the *App
    67  // associated with this group of mappings so you can set middleware, etc...
    68  // on that group, just as if you had used the a.Group functionality.
    69  /*
    70  	a.Resource("/users", &UsersResource{})
    71  
    72  	// Is equal to this:
    73  
    74  	ur := &UsersResource{}
    75  	g := a.Group("/users")
    76  	g.GET("/", ur.List) // GET /users => ur.List
    77  	g.GET("/new", ur.New) // GET /users/new => ur.New
    78  	g.GET("/{user_id}", ur.Show) // GET /users/{user_id} => ur.Show
    79  	g.GET("/{user_id}/edit", ur.Edit) // GET /users/{user_id}/edit => ur.Edit
    80  	g.POST("/", ur.Create) // POST /users => ur.Create
    81  	g.PUT("/{user_id}", ur.Update) PUT /users/{user_id} => ur.Update
    82  	g.DELETE("/{user_id}", ur.Destroy) DELETE /users/{user_id} => ur.Destroy
    83  */
    84  func (a *App) Resource(p string, r Resource) *App {
    85  	base := path.Base(p)
    86  	single := inflect.Singularize(base)
    87  	g := a.Group(p)
    88  	p = "/"
    89  
    90  	rv := reflect.ValueOf(r)
    91  	rt := rv.Type()
    92  	rname := fmt.Sprintf("%s.%s", rt.PkgPath(), rt.Name()) + ".%s"
    93  
    94  	spath := path.Join(p, fmt.Sprintf("{%s_id}", single))
    95  	setFuncKey(r.List, fmt.Sprintf(rname, "List"))
    96  	g.GET(p, r.List)
    97  	setFuncKey(r.New, fmt.Sprintf(rname, "New"))
    98  	g.GET(path.Join(p, "new"), r.New)
    99  	setFuncKey(r.Show, fmt.Sprintf(rname, "Show"))
   100  	g.GET(path.Join(spath), r.Show)
   101  	setFuncKey(r.Edit, fmt.Sprintf(rname, "Edit"))
   102  	g.GET(path.Join(spath, "edit"), r.Edit)
   103  	setFuncKey(r.Create, fmt.Sprintf(rname, "Create"))
   104  	g.POST(p, r.Create)
   105  	setFuncKey(r.Update, fmt.Sprintf(rname, "Update"))
   106  	g.PUT(path.Join(spath), r.Update)
   107  	setFuncKey(r.Destroy, fmt.Sprintf(rname, "Destroy"))
   108  	g.DELETE(path.Join(spath), r.Destroy)
   109  	return g
   110  }
   111  
   112  // ANY accepts a request across any HTTP method for the specified path
   113  // and routes it to the specified Handler.
   114  func (a *App) ANY(p string, h Handler) {
   115  	a.GET(p, h)
   116  	a.POST(p, h)
   117  	a.PUT(p, h)
   118  	a.PATCH(p, h)
   119  	a.HEAD(p, h)
   120  	a.OPTIONS(p, h)
   121  	a.DELETE(p, h)
   122  }
   123  
   124  // Group creates a new `*App` that inherits from it's parent `*App`.
   125  // This is useful for creating groups of end-points that need to share
   126  // common functionality, like middleware.
   127  /*
   128  	g := a.Group("/api/v1")
   129  	g.Use(AuthorizeAPIMiddleware)
   130  	g.GET("/users, APIUsersHandler)
   131  	g.GET("/users/:user_id, APIUserShowHandler)
   132  */
   133  func (a *App) Group(groupPath string) *App {
   134  	g := New(a.Options)
   135  
   136  	g.prefix = path.Join(a.prefix, groupPath)
   137  
   138  	g.router = a.router
   139  	g.Middleware = a.Middleware.clone()
   140  	g.ErrorHandlers = a.ErrorHandlers
   141  	g.root = a
   142  	if a.root != nil {
   143  		g.root = a.root
   144  	}
   145  	return g
   146  }
   147  
   148  func (a *App) addRoute(method string, url string, h Handler) RouteInfo {
   149  	a.moot.Lock()
   150  	defer a.moot.Unlock()
   151  
   152  	url = path.Join(a.prefix, url)
   153  
   154  	hs := funcKey(h)
   155  	r := RouteInfo{
   156  		Method:      method,
   157  		Path:        url,
   158  		HandlerName: hs,
   159  		Handler:     h,
   160  	}
   161  
   162  	r.MuxRoute = a.router.Handle(url, a.handlerToHandler(r, h)).Methods(method)
   163  
   164  	routes := a.Routes()
   165  	routes = append(routes, r)
   166  	sort.Sort(routes)
   167  	if a.root != nil {
   168  		a.root.routes = routes
   169  	} else {
   170  		a.routes = routes
   171  	}
   172  
   173  	return r
   174  }