github.com/lenfree/buffalo@v0.7.3-0.20170207163156-891616ea4064/router.go (about)

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