package mux import ( "fmt" "net/http" "strings" ) // Resource is a resourceful route provides a mapping between HTTP verbs and URLs and controller actions. // By convention, each action also maps to particular CRUD operations in a database. // A single entry in the routing file, such as // Index route // // GET /resource-name # index route // // GET /resource-name/new # create resource page // // POST /resource-name # create resource post // // GET /resource-name/:id # view resource // // GET /resource-name/:id/edit # edit resource // // PUT /resource-name/:id # update resource // // DELETE /resource-name/:id # delete resource type Resource struct { mux *http.ServeMux pattern string middlewares []func(http.Handler) http.Handler } func suffixIt(str, suffix string) string { var p strings.Builder p.WriteString(str) if !strings.HasSuffix(str, "/") { p.WriteString("/") } p.WriteString(suffix) return p.String() } // Index is GET /resource-name func (r *Resource) Index(h http.HandlerFunc) { r.handlerFunc(http.MethodGet, r.pattern, h) } // New is GET /resource-name/new func (r *Resource) New(h http.HandlerFunc) { r.handlerFunc(http.MethodGet, suffixIt(r.pattern, "new"), h) } // Create is POST /resource-name func (r *Resource) Create(h http.HandlerFunc) { r.handlerFunc(http.MethodPost, r.pattern, h) } // Show is GET /resource-name/:id func (r *Resource) Show(h http.HandlerFunc) { r.handlerFunc(http.MethodGet, suffixIt(r.pattern, "{id}"), h) } // Update is PUT /resource-name/:id func (r *Resource) Update(h http.HandlerFunc) { r.handlerFunc(http.MethodPut, suffixIt(r.pattern, "{id}"), h) } // PartialUpdate is PATCH /resource-name/:id func (r *Resource) PartialUpdate(h http.HandlerFunc) { r.handlerFunc(http.MethodPatch, suffixIt(r.pattern, "{id}"), h) } func (r *Resource) Destroy(h http.HandlerFunc) { r.handlerFunc(http.MethodDelete, suffixIt(r.pattern, "{id}"), h) } // handlerFunc registers the handler function for the given pattern. // If the given pattern conflicts, with one that is already registered, HandleFunc // panics. func (r *Resource) handlerFunc(method, pattern string, h http.HandlerFunc) { if r == nil { panic("serve: func handlerFunc() was called on nil") } if r.mux == nil { panic("serve: router mux is nil") } path := fmt.Sprintf("%s %s", method, pattern) r.mux.Handle(path, stack(r.middlewares, h)) } // Use will register middleware(s) on Router stack. func (r *Resource) Use(middlewares ...func(http.Handler) http.Handler) { if r == nil { panic("serve: func Use was called on nil") } r.middlewares = append(r.middlewares, middlewares...) }