overhaul of the rest package, made it a little bit more testable(WIP) and understandable

This commit is contained in:
Colin Henry 2020-08-22 16:55:32 -07:00
parent 4fe5a53450
commit d4a7732535
2 changed files with 40 additions and 29 deletions

View File

@ -10,32 +10,23 @@ import (
"github.com/jchenry/x/log" "github.com/jchenry/x/log"
) )
type CollectionStore interface { // Example: Resource(p, c, JSONEncoder, json.Decode(func()interface{}{return &foo{}}), log.None{})
All(params map[string][]string) (interface{}, error) func Resource(p *sync.Pool, g Gateway, e EntityEncoder, d encoding.Decoder, l log.Logger) http.HandlerFunc {
Get(id string) (interface{}, error) return restVerbHandler(
Delete(id string) error GetResource(g, e, l),
Update(e interface{}) error PostResource(g, d, p, l),
New(e interface{}) error PutResource(g, e, d, p, l),
} DeleteResource(g, l),
// Example: Collection(p, c, JSONEncoder, json.Decode(func()interface{}{return &foo{}}), log.None{})
func Collection(pool *sync.Pool, store CollectionStore, encode EntityEncoder, decode encoding.Decoder, log log.Logger) http.HandlerFunc {
return EntityHandler(
collectionGet(store, encode, log),
collectionPost(store, encode, decode, pool, log),
collectionPut(store, encode, decode, pool, log),
collectionDelete(store, encode, log),
) )
} }
func collectionGet(store CollectionStore, encode EntityEncoder, log log.Logger) http.HandlerFunc { func GetResource(store Readable, encode EntityEncoder, log log.Logger) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { // GET return func(w http.ResponseWriter, r *http.Request) { // GET
if id := filepath.Base(r.URL.Path); id != "" { if id := filepath.Base(r.URL.Path); id != "" {
if e, err := store.Get(id); err == nil { // handle individual entity if e, err := store.Read(id); err == nil { // handle individual entity
encode(w, e) encode(w, e)
} else { } else {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
encode(w, err)
log.Printf("Error: %s", err) log.Printf("Error: %s", err)
} }
} else { } else {
@ -43,25 +34,22 @@ func collectionGet(store CollectionStore, encode EntityEncoder, log log.Logger)
if e, err := store.All(params); err == nil { // handle all entities if e, err := store.All(params); err == nil { // handle all entities
encode(w, e) encode(w, e)
} else { } else {
// TODO: we really should write a header here, but need to figure out what it should be
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
log.Printf("Error: %s", err) log.Printf("Error: %s", err)
} }
} else { } else {
// encode(w, err)
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
} }
} }
} }
} }
func collectionPost(store CollectionStore, encode EntityEncoder, decode encoding.Decoder, pool *sync.Pool, log log.Logger) http.HandlerFunc { func PostResource(store Creatable, decode encoding.Decoder, pool *sync.Pool, log log.Logger) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { // POST TODO return func(w http.ResponseWriter, r *http.Request) { // POST TODO
e := pool.New() e := pool.Get()
defer pool.Put(e) defer pool.Put(e)
if err := decode(r.Body, e); err == nil { if err := decode(r.Body, e); err == nil {
if err = store.New(e); err == nil { if err = store.Create(e); err == nil {
w.WriteHeader(http.StatusCreated) w.WriteHeader(http.StatusCreated)
} else { } else {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
@ -73,9 +61,9 @@ func collectionPost(store CollectionStore, encode EntityEncoder, decode encoding
} }
} }
func collectionPut(store CollectionStore, encode EntityEncoder, decode encoding.Decoder, pool *sync.Pool, log log.Logger) http.HandlerFunc { func PutResource(store Updatable, encode EntityEncoder, decode encoding.Decoder, pool *sync.Pool, log log.Logger) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { // PUT TODO return func(w http.ResponseWriter, r *http.Request) { // PUT TODO
e := pool.New() e := pool.Get()
defer pool.Put(e) defer pool.Put(e)
if err := decode(r.Body, e); err == nil { if err := decode(r.Body, e); err == nil {
if err = store.Update(e); err == nil { if err = store.Update(e); err == nil {
@ -87,13 +75,11 @@ func collectionPut(store CollectionStore, encode EntityEncoder, decode encoding.
} }
} else { } else {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
encode(w, err)
} }
} }
} }
func collectionDelete(store CollectionStore, encode EntityEncoder, log log.Logger) http.HandlerFunc { func DeleteResource(store Deletable, log log.Logger) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { // DELETE TODO return func(w http.ResponseWriter, r *http.Request) { // DELETE TODO
if id := filepath.Base(r.URL.Path); id != "" { if id := filepath.Base(r.URL.Path); id != "" {
if err := store.Delete(id); err == nil { if err := store.Delete(id); err == nil {

25
rest/gateway.go Normal file
View File

@ -0,0 +1,25 @@
package rest
type Creatable interface {
Create(e interface{}) error
}
type Updatable interface {
Update(e interface{}) error
}
type Deletable interface {
Delete(id string) error
}
type Readable interface {
All(filters map[string][]string) (interface{}, error)
Read(id string) (interface{}, error)
}
type Gateway interface {
Creatable
Updatable
Deletable
Readable
}