194 lines
4.3 KiB
Go
194 lines
4.3 KiB
Go
package server
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"io"
|
|
"local/dndex/storage/entity"
|
|
"local/dndex/storage/operator"
|
|
"log"
|
|
"net/http"
|
|
"path"
|
|
"strings"
|
|
|
|
"gopkg.in/mgo.v2/bson"
|
|
)
|
|
|
|
type shortEntity struct {
|
|
Name string
|
|
ID string
|
|
}
|
|
|
|
func (rest *REST) entities(w http.ResponseWriter, r *http.Request) {
|
|
if scope, err := rest.entityScope(r); err != nil {
|
|
rest.respNotFound(w)
|
|
return
|
|
} else if r.Method != http.MethodGet && len(scope) > 1 {
|
|
r.Method = http.MethodPatch
|
|
}
|
|
switch r.Method {
|
|
case http.MethodPut:
|
|
rest.entitiesReplace(w, r)
|
|
case http.MethodPatch:
|
|
rest.entitiesUpdate(w, r)
|
|
case http.MethodPost:
|
|
rest.entitiesCreate(w, r)
|
|
case http.MethodGet:
|
|
rest.entitiesGet(w, r)
|
|
case http.MethodDelete:
|
|
rest.entitiesDelete(w, r)
|
|
default:
|
|
rest.respNotFound(w)
|
|
}
|
|
}
|
|
|
|
func (rest *REST) entitiesCreate(w http.ResponseWriter, r *http.Request) {
|
|
scope := rest.scope(r)
|
|
entityScope, _ := rest.entityScope(r)
|
|
one, err := rest.entityParse(r.Body)
|
|
if err != nil {
|
|
rest.respBadRequest(w, err.Error())
|
|
return
|
|
}
|
|
one.ID = entityScope[0]
|
|
if err := rest.g.Insert(r.Context(), scope.Namespace, one); err != nil {
|
|
rest.respError(w, err)
|
|
return
|
|
}
|
|
rest.entitiesGet(w, r)
|
|
}
|
|
|
|
func (rest *REST) entitiesDelete(w http.ResponseWriter, r *http.Request) {
|
|
scope := rest.scope(r)
|
|
if err := rest.g.Delete(r.Context(), scope.Namespace, bson.M{entity.ID: scope.EntityID}); err != nil {
|
|
rest.respError(w, err)
|
|
return
|
|
}
|
|
rest.respOK(w)
|
|
}
|
|
|
|
func (rest *REST) entitiesGet(w http.ResponseWriter, r *http.Request) {
|
|
entityScope, _ := rest.entityScope(r)
|
|
switch len(entityScope) {
|
|
case 0:
|
|
rest.entitiesList(w, r)
|
|
case 1:
|
|
rest.entitiesGetOne(w, r)
|
|
default:
|
|
rest.entitiesGetOneSub(w, r)
|
|
}
|
|
}
|
|
|
|
func (rest *REST) entitiesGetOne(w http.ResponseWriter, r *http.Request) {
|
|
scope := rest.scope(r)
|
|
entityScope, _ := rest.entityScope(r)
|
|
one, err := rest.g.Get(r.Context(), scope.Namespace, entityScope[0])
|
|
if err != nil {
|
|
rest.respNotFound(w)
|
|
return
|
|
}
|
|
rest.respMap(w, entityScope[0], one)
|
|
}
|
|
|
|
func (rest *REST) entitiesGetOneSub(w http.ResponseWriter, r *http.Request) {
|
|
entityScope, _ := rest.entityScope(r)
|
|
scope := rest.scope(r)
|
|
one, err := rest.g.Get(r.Context(), scope.Namespace, scope.EntityID)
|
|
if err != nil {
|
|
rest.respNotFound(w)
|
|
return
|
|
}
|
|
b, err := bson.Marshal(one)
|
|
if err != nil {
|
|
rest.respError(w, err)
|
|
return
|
|
}
|
|
var m bson.M
|
|
err = bson.Unmarshal(b, &m)
|
|
if err != nil {
|
|
rest.respError(w, err)
|
|
return
|
|
}
|
|
entityScope = entityScope[1:]
|
|
for len(entityScope) > 1 {
|
|
k := entityScope[0]
|
|
entityScope = entityScope[1:]
|
|
subm, ok := m[k]
|
|
if !ok {
|
|
m = nil
|
|
break
|
|
}
|
|
mm, ok := subm.(bson.M)
|
|
if !ok {
|
|
m = nil
|
|
break
|
|
}
|
|
m = mm
|
|
}
|
|
rest.respMap(w, scope.EntityID, m[entityScope[0]])
|
|
}
|
|
|
|
func (rest *REST) entitiesList(w http.ResponseWriter, r *http.Request) {
|
|
scope := rest.scope(r)
|
|
entities, err := rest.g.List(r.Context(), scope.Namespace)
|
|
if err != nil {
|
|
rest.respError(w, err)
|
|
return
|
|
}
|
|
short := make([]shortEntity, len(entities))
|
|
for i := range entities {
|
|
short[i] = shortEntity{Name: entities[i].Name, ID: entities[i].ID}
|
|
}
|
|
rest.respMap(w, scope.Namespace, short)
|
|
}
|
|
|
|
func (rest *REST) entitiesReplace(w http.ResponseWriter, r *http.Request) {
|
|
scope := rest.scope(r)
|
|
one, err := rest.entityParse(r.Body)
|
|
if err != nil {
|
|
rest.respBadRequest(w, err.Error())
|
|
return
|
|
}
|
|
if one.ID != scope.EntityID && one.ID != "" {
|
|
rest.respBadRequest(w, "cannot change primary key")
|
|
return
|
|
}
|
|
one.ID = scope.EntityID
|
|
err = rest.g.Update(r.Context(), scope.Namespace, bson.M{entity.ID: scope.EntityID}, operator.SetMany{Value: one})
|
|
if err != nil {
|
|
rest.respError(w, err)
|
|
return
|
|
}
|
|
rest.entitiesGet(w, r)
|
|
}
|
|
|
|
func (rest *REST) entitiesUpdate(w http.ResponseWriter, r *http.Request) {
|
|
log.Println(r.Method)
|
|
log.Println(rest.entityScope(r))
|
|
http.Error(w, "not impl", http.StatusNotImplemented)
|
|
}
|
|
|
|
func (rest *REST) entityParse(r io.Reader) (entity.One, error) {
|
|
var one entity.One
|
|
err := json.NewDecoder(r).Decode(&one)
|
|
return one, err
|
|
}
|
|
|
|
func (rest *REST) entityScope(r *http.Request) ([]string, error) {
|
|
p := r.URL.Path
|
|
if path.Dir(p) == path.Base(p) {
|
|
if r.Method == http.MethodGet {
|
|
return []string{}, nil
|
|
}
|
|
return nil, errors.New("nothing specified")
|
|
}
|
|
ps := strings.Split(p, "/")
|
|
ps2 := []string{}
|
|
for i := range ps {
|
|
if ps[i] != "" {
|
|
ps2 = append(ps2, ps[i])
|
|
}
|
|
}
|
|
return ps2, nil
|
|
}
|