almost there
parent
c4b63825aa
commit
f41b34aa5c
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue