2020-07-08 21:59:37 -04:00
|
|
|
package rest
|
|
|
|
|
|
|
|
import (
|
|
|
|
"net/http"
|
|
|
|
"net/url"
|
|
|
|
"path/filepath"
|
|
|
|
"sync"
|
|
|
|
|
|
|
|
"github.com/jchenry/x/encoding"
|
2020-08-22 18:54:49 -04:00
|
|
|
"github.com/jchenry/x/log"
|
2020-07-08 21:59:37 -04:00
|
|
|
)
|
|
|
|
|
2020-08-22 19:55:32 -04:00
|
|
|
// Example: Resource(p, c, JSONEncoder, json.Decode(func()interface{}{return &foo{}}), log.None{})
|
|
|
|
func Resource(p *sync.Pool, g Gateway, e EntityEncoder, d encoding.Decoder, l log.Logger) http.HandlerFunc {
|
|
|
|
return restVerbHandler(
|
|
|
|
GetResource(g, e, l),
|
|
|
|
PostResource(g, d, p, l),
|
|
|
|
PutResource(g, e, d, p, l),
|
|
|
|
DeleteResource(g, l),
|
2020-07-08 21:59:37 -04:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2020-08-22 19:55:32 -04:00
|
|
|
func GetResource(store Readable, encode EntityEncoder, log log.Logger) http.HandlerFunc {
|
2020-07-08 21:59:37 -04:00
|
|
|
return func(w http.ResponseWriter, r *http.Request) { // GET
|
|
|
|
if id := filepath.Base(r.URL.Path); id != "" {
|
2020-08-22 19:55:32 -04:00
|
|
|
if e, err := store.Read(id); err == nil { // handle individual entity
|
2020-07-08 21:59:37 -04:00
|
|
|
encode(w, e)
|
|
|
|
} else {
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
2020-08-22 18:54:49 -04:00
|
|
|
log.Printf("Error: %s", err)
|
2020-07-08 21:59:37 -04:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if params, err := url.ParseQuery(r.URL.RawQuery); err == nil {
|
|
|
|
if e, err := store.All(params); err == nil { // handle all entities
|
|
|
|
encode(w, e)
|
|
|
|
} else {
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
2020-08-22 18:54:49 -04:00
|
|
|
log.Printf("Error: %s", err)
|
2020-07-08 21:59:37 -04:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-22 19:55:32 -04:00
|
|
|
func PostResource(store Creatable, decode encoding.Decoder, pool *sync.Pool, log log.Logger) http.HandlerFunc {
|
2020-07-08 21:59:37 -04:00
|
|
|
return func(w http.ResponseWriter, r *http.Request) { // POST TODO
|
2020-08-22 19:55:32 -04:00
|
|
|
e := pool.Get()
|
2020-07-08 21:59:37 -04:00
|
|
|
defer pool.Put(e)
|
|
|
|
if err := decode(r.Body, e); err == nil {
|
2020-08-22 19:55:32 -04:00
|
|
|
if err = store.Create(e); err == nil {
|
2020-07-08 21:59:37 -04:00
|
|
|
w.WriteHeader(http.StatusCreated)
|
|
|
|
} else {
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
2020-08-22 18:54:49 -04:00
|
|
|
log.Printf("Error: %s", err)
|
2020-07-08 21:59:37 -04:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-22 19:55:32 -04:00
|
|
|
func PutResource(store Updatable, encode EntityEncoder, decode encoding.Decoder, pool *sync.Pool, log log.Logger) http.HandlerFunc {
|
2020-07-08 21:59:37 -04:00
|
|
|
return func(w http.ResponseWriter, r *http.Request) { // PUT TODO
|
2020-08-22 19:55:32 -04:00
|
|
|
e := pool.Get()
|
2020-07-08 21:59:37 -04:00
|
|
|
defer pool.Put(e)
|
|
|
|
if err := decode(r.Body, e); err == nil {
|
|
|
|
if err = store.Update(e); err == nil {
|
|
|
|
w.WriteHeader(http.StatusAccepted)
|
|
|
|
encode(w, e)
|
|
|
|
} else {
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
2020-08-22 18:54:49 -04:00
|
|
|
log.Printf("Error: %s", err)
|
2020-07-08 21:59:37 -04:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-22 19:55:32 -04:00
|
|
|
func DeleteResource(store Deletable, log log.Logger) http.HandlerFunc {
|
2020-07-08 21:59:37 -04:00
|
|
|
return func(w http.ResponseWriter, r *http.Request) { // DELETE TODO
|
|
|
|
if id := filepath.Base(r.URL.Path); id != "" {
|
|
|
|
if err := store.Delete(id); err == nil {
|
|
|
|
w.WriteHeader(http.StatusNoContent)
|
|
|
|
} else {
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
2020-08-22 18:54:49 -04:00
|
|
|
log.Printf("Error: %s", err)
|
2020-07-08 21:59:37 -04:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|