diff options
| -rw-r--r-- | model/object.go | 1 | ||||
| -rw-r--r-- | model/recipe.go | 14 | ||||
| -rw-r--r-- | model/recipes.go | 4 | ||||
| -rw-r--r-- | server.go | 6 | ||||
| -rw-r--r-- | view/json.go | 65 |
5 files changed, 90 insertions, 0 deletions
diff --git a/model/object.go b/model/object.go index 63ef419..0b1919b 100644 --- a/model/object.go +++ b/model/object.go @@ -9,4 +9,5 @@ type Object interface { Read(tx *sql.Tx) error Update(tx *sql.Tx) error Delete(tx *sql.Tx) error + SetID(id int) } diff --git a/model/recipe.go b/model/recipe.go index 684b158..adcafa1 100644 --- a/model/recipe.go +++ b/model/recipe.go @@ -5,6 +5,8 @@ import ( "encoding/json" "errors" "fmt" + "log" + "strconv" ) type Recipe struct { @@ -19,11 +21,23 @@ type Recipe struct { IsFavorite bool `json:"is_favorite"` } +func NewRecipe() Object { + return &Recipe{} +} + func (r Recipe) String() string { b, _ := json.MarshalIndent(r, "", " ") return string(b) } +func (r *Recipe) SetID(id int) { + if r == nil { + log.Println("Got nil as recipe!") + } + + r.Id = strconv.Itoa(id) +} + func (r *Recipe) Validate() error { var err error diff --git a/model/recipes.go b/model/recipes.go index e4fd1b8..b711dab 100644 --- a/model/recipes.go +++ b/model/recipes.go @@ -14,6 +14,10 @@ type RecipesElement struct { type Recipes []RecipesElement +func (r *Recipes) SetID(id int) { + // singleton object, ignoring ID +} + func (r *Recipes) Create(tx *sql.Tx) error { return fmt.Errorf("Impossible to create a recipe list") } @@ -30,9 +30,15 @@ func NewServer(addr string, db *model.DB) *Server { mux.Handle("GET /recipes", view.RecipesRead(db)) mux.Handle("GET /recipe/create", view.RecipeCreate()) + + mux.Handle("POST /api/recipe", view.CreateJSON[*model.Recipe](db, model.NewRecipe)) mux.Handle("POST /recipe", controller.RecipeCreate(db)) + + mux.Handle("GET /api/recipe/{id}", view.ReadJSON[*model.Recipe](db, model.NewRecipe)) mux.Handle("GET /recipe/{id}", view.RecipeRead(db)) + mux.Handle("POST /recipe/{id}", controller.RecipeUpdate(db)) + mux.Handle("DELETE /recipe/{id}", controller.RecipeDelete(db)) mux.Handle("GET /favicon.ico", view.FaviconRead()) diff --git a/view/json.go b/view/json.go new file mode 100644 index 0000000..5f3a30c --- /dev/null +++ b/view/json.go @@ -0,0 +1,65 @@ +package view + +import ( + "encoding/json" + "io" + "log" + "net/http" + "strconv" + + "xengineering.eu/ceres/model" +) + +func CreateJSON[O model.Object](db *model.DB, constructor func() model.Object) http.Handler { + return http.HandlerFunc( + func(w http.ResponseWriter, r *http.Request) { + buf, err := io.ReadAll(r.Body) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + object := constructor() + err = json.Unmarshal(buf, &object) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + + err = db.Transaction(object.Create) + if err != nil { + log.Println("Could not create object.") + http.Error(w, "Could not create object.", http.StatusBadRequest) + return + } + }, + ) +} + +func ReadJSON[O model.Object](db *model.DB, constructor func() model.Object) http.Handler { + return http.HandlerFunc( + func(w http.ResponseWriter, r *http.Request) { + object := constructor() + + id, err := strconv.Atoi(r.PathValue("id")) + if err != nil { + // TODO + return + } + object.SetID(id) + + err = db.Transaction(object.Read) + if err != nil { + // TODO + return + } + + w.Header().Set("Content-Type", "application/json") + err = json.NewEncoder(w).Encode(object) + if err != nil { + // TODO + return + } + }, + ) +} |
