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 }