almost there

master
Bel LaPointe 2022-02-09 12:30:12 -07:00
parent c4b63825aa
commit f41b34aa5c
3 changed files with 142 additions and 45 deletions

View File

@ -10,6 +10,7 @@ import (
"local/router"
"local/simpleserve/simpleserve"
"net/http"
"net/url"
"os"
"path"
"regexp"
@ -72,26 +73,8 @@ func (server *Server) tryCatchHttpHandler(handler func(http.ResponseWriter, *htt
}
func (server *Server) apiV0TreeHandler(w http.ResponseWriter, r *http.Request) error {
_, pretty := r.URL.Query()["pretty"]
if pretty {
return server.apiV0TreePrettyHandler(w, r)
}
return server.apiV0TreePlainHandler(w, r)
}
func (server *Server) apiV0TreePrettyHandler(w http.ResponseWriter, r *http.Request) error {
tree := server.tree()
//branches, err := tree.GetPretty()
branches, err := tree.GetRoot()
if err != nil {
return err
}
return json.NewEncoder(w).Encode(branches)
}
func (server *Server) apiV0TreePlainHandler(w http.ResponseWriter, r *http.Request) error {
tree := server.tree()
branches, err := tree.GetRoot()
branches, err := tree.GetRootMeta()
if err != nil {
return err
}
@ -106,7 +89,8 @@ func ensureAndWrite(p string, b []byte) error {
}
func (server *Server) apiV0MediaHandler(w http.ResponseWriter, r *http.Request) error {
id, err := server.postContentHandler(path.Dir(server.diskMediaPath("id")), w, r)
id := uuid.New().String()
id, err := server.postContentHandler(server.diskMediaPath(id), w, r)
if err != nil {
return err
}
@ -157,11 +141,10 @@ func (server *Server) getContentHandler(filePath string, w http.ResponseWriter,
return nil
}
func (server *Server) postContentHandler(fileDir string, w http.ResponseWriter, r *http.Request) (string, error) {
func (server *Server) postContentHandler(filePath string, w http.ResponseWriter, r *http.Request) (string, error) {
if r.Method != http.MethodPost {
return "", errors.New("not found")
}
id := strings.Split(uuid.New().String(), "-")[0]
if strings.HasPrefix(r.Header.Get("Content-Type"), "multipart/form-data") {
kb := int64(1 << 10)
mb := kb << 10
@ -179,7 +162,7 @@ func (server *Server) postContentHandler(fileDir string, w http.ResponseWriter,
if h, ok := infos[0].Header["Content-Type"]; ok {
ext = path.Base(h[0])
}
id += "." + ext
filePath += "." + ext
f, err := infos[0].Open()
if err != nil {
return "", err
@ -193,8 +176,7 @@ func (server *Server) postContentHandler(fileDir string, w http.ResponseWriter,
}
return "", fmt.Errorf("parse form: %+v", r.PostForm)
}
filePath := path.Join(fileDir, id)
return id, server.putContentHandler(filePath, w, r)
return filePath, server.putContentHandler(filePath, w, r)
}
func (server *Server) putContentHandler(filePath string, w http.ResponseWriter, r *http.Request) error {
@ -210,8 +192,8 @@ func (server *Server) rootHandler(w http.ResponseWriter, r *http.Request) error
return server.getContentHandler(path.Join(server.root, "index.html"), w, r)
}
func (server *Server) tree() *Tree {
return nil
func (server *Server) tree() Tree {
return NewTree(path.Join(server.root, "files"))
}
func (server *Server) diskMediaPath(id string) string {
@ -223,7 +205,80 @@ func (server *Server) apiV0FilesHandler(w http.ResponseWriter, r *http.Request)
}
func (server *Server) apiV0FilesIDHandler(w http.ResponseWriter, r *http.Request) error {
return errors.New("not impl")
switch r.Method {
case http.MethodGet:
return server.apiV0FilesIDGetHandler(w, r)
case http.MethodPut:
return server.apiV0FilesIDPutHandler(w, r)
case http.MethodDelete:
return server.apiV0FilesIDDelHandler(w, r)
}
http.NotFound(w, r)
return nil
}
func (server *Server) apiV0FilesIDGetHandler(w http.ResponseWriter, r *http.Request) error {
id := server.fileId(r)
leaf, err := server.tree().Get(id)
if os.IsNotExist(err) {
http.NotFound(w, r)
return nil
} else if err != nil {
return err
}
w.Header().Set("Title", leaf.Title)
_, err = w.Write([]byte(leaf.Content))
return err
}
func (server *Server) apiV0FilesIDDelHandler(w http.ResponseWriter, r *http.Request) error {
id := server.fileId(r)
leaf, err := server.tree().Get(id)
if os.IsNotExist(err) {
return nil
} else if err != nil {
return err
}
leaf.Deleted = true
return server.tree().Put(id, leaf)
}
func (server *Server) urlFileId(id []string) string {
if len(id) == 0 {
return ""
}
for i := 1; i < len(id); i++ {
id[0] = strings.Join([]string{id[0], url.PathEscape(id[i])}, "/")
}
return id[0]
}
func (server *Server) fileId(r *http.Request) []string {
return strings.Split(strings.TrimPrefix(r.URL.Path, "/api/v0/files/"), "/")
}
func (server *Server) apiV0FilesIDPutHandler(w http.ResponseWriter, r *http.Request) error {
id := server.fileId(r)
leaf, err := server.tree().Get(id)
if os.IsNotExist(err) {
} else if err != nil {
return err
}
b, err := ioutil.ReadAll(r.Body)
if err != nil {
return err
}
leaf.Content = string(b)
leaf.Title = r.Header.Get("Title")
leaf.Deleted = false
return server.tree().Put(id, leaf)
}
func (server *Server) apiV0SearchHandler(w http.ResponseWriter, r *http.Request) error {
@ -245,5 +300,21 @@ func (server *Server) apiV0SearchHandler(w http.ResponseWriter, r *http.Request)
w.Write([]byte(`[]`))
return nil
}
return errors.New("not impl")
tree, err := server.tree().GetRoot()
if err != nil {
return err
}
result := []string{}
if err := tree.ForEach(func(id []string, leaf Leaf) error {
for _, pattern := range patterns {
if !pattern.MatchString(leaf.Content) && !pattern.MatchString(fmt.Sprint(id)) {
return nil
}
}
result = append(result, server.urlFileId(id))
return nil
}); err != nil {
return err
}
return json.NewEncoder(w).Encode(result)
}

View File

@ -1,6 +1,13 @@
package main
/*
import (
"net/http"
"net/http/httptest"
"path"
"strings"
"testing"
)
func TestServerRoutes(t *testing.T) {
server := NewServer(t.TempDir())
if err := server.Routes(); err != nil {
@ -11,15 +18,16 @@ func TestServerRoutes(t *testing.T) {
t.Fatal(err)
}
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"))
if err := server.tree().Put("putfid", Branch{}); err != nil {
tree := server.tree()
if err := tree.Put([]string{"getfid"}, Leaf{Title: "", Content: "getfid body"}); err != nil {
t.Fatal(err)
}
server.tree().Put("delfid", Branch{Title: "delfid title"})
server.tree().Put("getfid", Branch{Title: "getfid title"})
tree.Put([]string{"putfid"}, Leaf{Title: "putfid title", Content: "initial putfid body"})
tree.Put([]string{"delfid"}, Leaf{Title: "delfid title", Content: "delfid body"})
t.Log(tree.GetRoot())
ensureAndWrite(path.Join(server.root, "index.html"), []byte("mom"))
cases := map[string]struct {
path string
@ -37,15 +45,10 @@ func TestServerRoutes(t *testing.T) {
method: http.MethodGet,
want: `["getfid"]`,
},
"v0: tree: get pretty": {
path: "/api/v0/tree?pretty",
method: http.MethodGet,
want: `"getfid":{"Children":{`,
},
"v0: tree: get": {
path: "/api/v0/tree",
method: http.MethodGet,
want: `":{"Title":"getfid title",`,
want: `"Title":"Untitled",`,
},
"v0: media: post": {
path: "/api/v0/media",
@ -101,6 +104,7 @@ func TestServerRoutes(t *testing.T) {
}
}
/*
func TestServerPutTreeGetFile(t *testing.T) {
server := NewServer(t.TempDir())
if err := server.Routes(); err != nil {

View File

@ -9,8 +9,8 @@ import (
)
type Branch struct {
Leaf Leaf
Branches map[string]Branch
Leaf Leaf `json:"Leaf,omitempty"`
Branches map[string]Branch `json:"Branches,omitempty"`
}
func (branch Branch) IsZero() bool {
@ -29,6 +29,24 @@ func (branch Branch) Find(baseId string) ([]string, bool) {
return nil, false
}
func (branch Branch) ForEach(foo func([]string, Leaf) error) error {
return branch.forEach([]string{}, foo)
}
func (branch Branch) forEach(preid []string, foo func([]string, Leaf) error) error {
if err := foo(preid, branch.Leaf); err != nil {
return err
}
postid := append(preid, "")
for id, child := range branch.Branches {
postid[len(postid)-1] = id
if err := child.forEach(postid, foo); err != nil {
return err
}
}
return nil
}
type Leaf struct {
Title string
Deleted bool
@ -39,6 +57,9 @@ func (base Leaf) Merge(updated Leaf) Leaf {
if updated.Title != "" {
base.Title = updated.Title
}
if base.Title == "" {
base.Title = "Untitled"
}
base.Deleted = updated.Deleted
base.Content = updated.Content
return base
@ -55,6 +76,7 @@ func NewTree(root string) Tree {
func (tree Tree) WithRoot(root string) Tree {
tree.root = root
tree.cachedRoot = Branch{}
return tree
}