diff --git a/spike/review/reinvent/ezmded/server/server.go b/spike/review/reinvent/ezmded/server/server.go index 7817009..b99bf46 100644 --- a/spike/review/reinvent/ezmded/server/server.go +++ b/spike/review/reinvent/ezmded/server/server.go @@ -10,6 +10,7 @@ import ( "os" "path" "strings" + "time" "github.com/google/uuid" ) @@ -113,10 +114,6 @@ func (server *Server) apiV0MediaIDGetHandler(w http.ResponseWriter, r *http.Requ return server.getContentHandler(server.diskMediaPath(id), w, r) } -func (server *Server) apiV0FilesHandler(w http.ResponseWriter, r *http.Request) error { - return errors.New("not impl: apiV0FilesHandler") -} - func (server *Server) getContentHandler(filePath string, w http.ResponseWriter, r *http.Request) error { if r.Method != http.MethodGet { return errors.New("not found") @@ -138,6 +135,10 @@ func (server *Server) postContentHandler(filePath string, w http.ResponseWriter, if r.Method != http.MethodPost { return errors.New("not found") } + return server.putContentHandler(filePath, w, r) +} + +func (server *Server) putContentHandler(filePath string, w http.ResponseWriter, r *http.Request) error { defer r.Body.Close() b, err := ioutil.ReadAll(r.Body) if err != nil { @@ -146,14 +147,6 @@ func (server *Server) postContentHandler(filePath string, w http.ResponseWriter, return ensureAndWrite(filePath, b) } -func (server *Server) apiV0FilesIDHandler(w http.ResponseWriter, r *http.Request) error { - return errors.New("not impl" + r.URL.Path) -} - -func (server *Server) apiV0SearchHandler(w http.ResponseWriter, r *http.Request) error { - return errors.New("not impl" + r.URL.Path) -} - func (server *Server) rootHandler(w http.ResponseWriter, r *http.Request) error { return server.getContentHandler(path.Join(server.root, "index.html"), w, r) } @@ -162,6 +155,91 @@ func (server *Server) tree() *Tree { return NewTree(path.Join(server.root, "tree.yaml")) } +func (server *Server) diskFilePath(id string) string { + return path.Join(server.root, "files", id) +} + func (server *Server) diskMediaPath(id string) string { return path.Join(server.root, "media", id) } + +func (server *Server) apiV0FilesHandler(w http.ResponseWriter, r *http.Request) error { + id := uuid.New().String() + filePath := server.diskFilePath(id) + if err := server.postContentHandler(filePath, w, r); err != nil { + return err + } + return json.NewEncoder(w).Encode(map[string]map[string]string{ + "data": map[string]string{ + "filePath": path.Join("/api/v0/files", id), + }, + }) +} + +func (server *Server) apiV0FilesIDHandler(w http.ResponseWriter, r *http.Request) error { + switch r.Method { + case http.MethodPut: + return server.apiV0FilesIDPutHandler(w, r) + case http.MethodGet: + return server.apiV0FilesIDGetHandler(w, r) + case http.MethodDelete: + return server.apiV0FilesIDDelHandler(w, r) + } + http.NotFound(w, r) + return nil +} + +func (server *Server) apiV0FilesIDPutHandler(w http.ResponseWriter, r *http.Request) error { + id := path.Base(r.URL.Path) + tree := server.tree() + branches, err := tree.Get() + if err != nil { + return err + } + branch, ok := branches[id] + if !ok { + http.NotFound(w, r) + return nil + } + branch.Updated = time.Now().UTC() + if title := r.Header.Get("Title"); title != "" { + branch.Title = title + } + branch.Deleted = false + if err := server.putContentHandler(server.diskFilePath(id), w, r); err != nil { + return err + } + return tree.Put(id, branch) +} + +func (server *Server) apiV0FilesIDGetHandler(w http.ResponseWriter, r *http.Request) error { + tree := server.tree() + branches, err := tree.Get() + if err != nil { + return err + } + id := path.Base(r.URL.Path) + branch, _ := branches[id] + w.Header().Set("Title", branch.Title) + return server.getContentHandler(server.diskFilePath(id), w, r) +} + +func (server *Server) apiV0FilesIDDelHandler(w http.ResponseWriter, r *http.Request) error { + tree := server.tree() + branches, err := tree.Get() + if err != nil { + return err + } + id := path.Base(r.URL.Path) + branch, ok := branches[id] + if !ok { + return nil + } + branch.Deleted = true + branch.Updated = time.Now().UTC() + return tree.Put(id, branch) +} + +func (server *Server) apiV0SearchHandler(w http.ResponseWriter, r *http.Request) error { + return errors.New("not impl" + r.URL.Path) +} diff --git a/spike/review/reinvent/ezmded/server/server_test.go b/spike/review/reinvent/ezmded/server/server_test.go index 7488c6e..88e9b1e 100644 --- a/spike/review/reinvent/ezmded/server/server_test.go +++ b/spike/review/reinvent/ezmded/server/server_test.go @@ -17,11 +17,18 @@ func TestServerRoutes(t *testing.T) { ensureAndWrite(server.diskMediaPath("id"), []byte("hi")) ensureAndWrite(server.diskMediaPath("delid"), []byte("hi")) + ensureAndWrite(server.diskFilePath("getfid"), []byte("getfid body")) + ensureAndWrite(server.diskFilePath("putfid"), []byte("initial putfid body")) + ensureAndWrite(server.diskFilePath("delfid"), []byte("delfid body")) ensureAndWrite(path.Join(server.root, "index.html"), []byte("mom")) + server.tree().Put("putfid", Branch{}) + server.tree().Put("delfid", Branch{Title: "delfid title"}) + server.tree().Put("getfid", Branch{Title: "getfid title"}) cases := map[string]struct { path string method string + body string want string }{ "v0: /: get": { @@ -36,7 +43,7 @@ func TestServerRoutes(t *testing.T) { "v0: tree: get": { path: "/api/v0/tree", method: http.MethodGet, - want: "{}", + want: `{"delfid":{"Title":"delfid title",`, }, "v0: media: post": { path: "/api/v0/media", @@ -57,15 +64,25 @@ func TestServerRoutes(t *testing.T) { method: http.MethodPost, }, "v0: files id: get": { - path: "/api/v0/files/id", + path: "/api/v0/files/getfid", method: http.MethodGet, + want: "getfid body", + }, + "v0: files id: put": { + path: "/api/v0/files/putfid", + method: http.MethodPut, + body: "putfid body", + }, + "v0: files id: del": { + path: "/api/v0/files/delfid", + method: http.MethodDelete, }, } for name, d := range cases { c := d t.Run(name, func(t *testing.T) { - r := httptest.NewRequest(c.method, c.path, nil) + r := httptest.NewRequest(c.method, c.path, strings.NewReader(c.body)) w := httptest.NewRecorder() server.ServeHTTP(w, r) if w.Code == http.StatusNotFound { @@ -78,7 +95,7 @@ func TestServerRoutes(t *testing.T) { if len(c.want) > 0 && !strings.Contains(string(w.Body.Bytes()), c.want) { t.Fatal(w) } - t.Logf("%s %s => %s", c.method, c.path, w.Body.Bytes()) + t.Logf("%s %s (%+v) => %s", c.method, c.path, w.Header(), w.Body.Bytes()) } }) }