diff --git a/api.go b/api.go new file mode 100644 index 0000000..c3dcce1 --- /dev/null +++ b/api.go @@ -0,0 +1,25 @@ +package main + +import ( + "encoding/json" + "net/http" +) + +func apiPostCreate(w http.ResponseWriter, r *http.Request) { + defer func() { + _ = r.Body.Close() + }() + post := &Post{} + err := json.NewDecoder(r.Body).Decode(post) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + err = createPost(post) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + w.Header().Set("Location", post.Path) + w.WriteHeader(http.StatusCreated) +} diff --git a/http.go b/http.go index b38d4d8..dc3fdff 100644 --- a/http.go +++ b/http.go @@ -17,8 +17,10 @@ import ( const contentTypeHTML = "text/html" +var d *dynamicHandler + func startServer() error { - d := newDynamicHandler() + d = newDynamicHandler() h, err := buildHandler() if err != nil { return err @@ -49,6 +51,15 @@ func startServer() error { return nil } +func reloadRouter() error { + h, err := buildHandler() + if err != nil { + return err + } + d.swapHandler(h) + return nil +} + func buildHandler() (http.Handler, error) { r := chi.NewRouter() @@ -60,6 +71,11 @@ func buildHandler() (http.Handler, error) { r.Use(middleware.StripSlashes) r.Use(middleware.GetHead) + r.Route("/api", func(apiRouter chi.Router) { + // TODO: Auth + apiRouter.Post("/post", apiPostCreate) + }) + allPostPaths, err := allPostPaths() if err != nil { return nil, err diff --git a/posts.go b/posts.go index b239841..781787c 100644 --- a/posts.go +++ b/posts.go @@ -5,16 +5,17 @@ import ( "database/sql" "errors" "net/http" + "strings" ) var errPostNotFound = errors.New("post not found") type Post struct { - Path string - Content string - Published string - Updated string - Parameters map[string]string + Path string `json:"path"` + Content string `json:"content"` + Published string `json:"published"` + Updated string `json:"updated"` + Parameters map[string]string `json:"parameters"` } func servePost(w http.ResponseWriter, r *http.Request) { @@ -74,3 +75,35 @@ func allPostPaths() ([]string, error) { } return postPaths, nil } + +func createPost(post *Post) error { + if post == nil { + return nil + } + if post.Path == "" || !strings.HasPrefix(post.Path, "/") { + return errors.New("wrong path") + } + startWritingToDb() + tx, err := appDb.Begin() + if err != nil { + return err + } + _, err = tx.Exec("insert into posts (path, content, published, updated) values (?, ?, ?, ?)", post.Path, post.Content, post.Published, post.Updated) + if err != nil { + _ = tx.Rollback() + return err + } + for param, value := range post.Parameters { + _, err = tx.Exec("insert into post_parameters (path, parameter, value) values (?, ?, ?)", post.Path, param, value) + if err != nil { + _ = tx.Rollback() + return err + } + } + err = tx.Commit() + if err != nil { + return err + } + finishWritingToDb() + return reloadRouter() +}