From e9f20850ef66502ed772fdb95553f012e7d54337 Mon Sep 17 00:00:00 2001 From: Ruidy Nemausat Date: Wed, 15 Jul 2020 11:03:11 +0200 Subject: [PATCH] =?UTF-8?q?=E2=8C=AB=20enable=20delete=20product?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- products/data/product.go | 10 ++++++++ products/handlers/delete.go | 34 +++++++++++++++++++++++++++ products/handlers/post.go | 23 +++++++++++++++++++ products/handlers/products.go | 43 +++++++---------------------------- products/handlers/put.go | 38 +++++++++++++++++++++++++++++++ products/handlers/routes.go | 5 +++- swagger.yaml | 29 +++++++++++++++++++++++ 7 files changed, 146 insertions(+), 36 deletions(-) create mode 100644 products/handlers/delete.go create mode 100644 products/handlers/post.go create mode 100644 products/handlers/put.go diff --git a/products/data/product.go b/products/data/product.go index 9d3ea5f..20ce968 100644 --- a/products/data/product.go +++ b/products/data/product.go @@ -39,6 +39,16 @@ func UpdateProduct(id int, p *models.Product) error { return nil } +// DeleteProduct removes a Product idntified by its id +func DeleteProduct(id int) error { + idx, _, err := findProduct(id) + if err != nil { + return err + } + productList = append(productList[0:idx], productList[idx+1:]...) + return nil +} + // ErrorProductNotFound its thrown when the product is not found var ErrorProductNotFound = fmt.Errorf("Product not found") diff --git a/products/handlers/delete.go b/products/handlers/delete.go new file mode 100644 index 0000000..a4bfc83 --- /dev/null +++ b/products/handlers/delete.go @@ -0,0 +1,34 @@ +package handlers + +import ( + "fmt" + "net/http" + "strconv" + + "github.com/gorilla/mux" + "github.com/rjNemo/go-micro/products/data" +) + +// swagger:route DELETE /products/{id} products product +// Deletes a product +// responses: +// 200: productResponse + +// DeleteProduct edit product identified by id +func (p *Products) DeleteProduct(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + id, _ := strconv.Atoi(vars["id"]) + + p.logger.Println("Handle 'DELETE' request", id) + + err := data.DeleteProduct(id) + if err == data.ErrorProductNotFound { + http.Error(w, err.Error(), http.StatusNotFound) + return + } + if err != nil { + errMsg := fmt.Sprintf("something went wrong: %s", err.Error()) + http.Error(w, errMsg, http.StatusInternalServerError) + return + } +} diff --git a/products/handlers/post.go b/products/handlers/post.go new file mode 100644 index 0000000..799b713 --- /dev/null +++ b/products/handlers/post.go @@ -0,0 +1,23 @@ +package handlers + +import ( + "net/http" + + "github.com/rjNemo/go-micro/products/data" + "github.com/rjNemo/go-micro/products/models" +) + +// swagger:route POST /products products product +// Creates a product +// responses: +// 201: productResponse + +// AddProduct reads request body and creates new product +func (p *Products) AddProduct(w http.ResponseWriter, r *http.Request) { + p.logger.Println("Handle 'POST' request") + // get product from the request + newProd := r.Context().Value(KeyProduct{}).(*models.Product) // cast into a Product + + p.logger.Printf("product: %#v", newProd) + data.AddProduct(newProd) +} diff --git a/products/handlers/products.go b/products/handlers/products.go index c8f875d..a85b9eb 100644 --- a/products/handlers/products.go +++ b/products/handlers/products.go @@ -19,10 +19,7 @@ import ( "fmt" "log" "net/http" - "strconv" - "github.com/gorilla/mux" - "github.com/rjNemo/go-micro/products/data" "github.com/rjNemo/go-micro/products/models" ) @@ -39,43 +36,19 @@ type productsResponse struct { Body []models.Product } +// product in the response. For go-swagger +// swagger:response productResponse +type productResponse struct { + // One product in the datastore + // in: body + Body models.Product +} + // New creates a Products handler func New(logger *log.Logger) *Products { return &Products{logger: logger} } -// AddProduct reads request body and creates new product -func (p *Products) AddProduct(w http.ResponseWriter, r *http.Request) { - p.logger.Println("Handle 'POST' request") - // get product from the request - newProd := r.Context().Value(KeyProduct{}).(*models.Product) // cast into a Product - - p.logger.Printf("product: %#v", newProd) - data.AddProduct(newProd) -} - -// UpdateProduct edit product identified by id -func (p *Products) UpdateProduct(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - id, _ := strconv.Atoi(vars["id"]) - - p.logger.Println("Handle 'PUT' request", id) - // get product from the request - newProd := r.Context().Value(KeyProduct{}).(*models.Product) // cast into a Product - - p.logger.Printf("product: %#v", newProd) - err := data.UpdateProduct(id, newProd) - if err == data.ErrorProductNotFound { - http.Error(w, err.Error(), http.StatusNotFound) - return - } - if err != nil { - errMsg := fmt.Sprintf("something went wrong: %s", err.Error()) - http.Error(w, errMsg, http.StatusInternalServerError) - return - } -} - // KeyProduct is a key used to pass validated product to handler type KeyProduct struct{} diff --git a/products/handlers/put.go b/products/handlers/put.go new file mode 100644 index 0000000..5f1aee8 --- /dev/null +++ b/products/handlers/put.go @@ -0,0 +1,38 @@ +package handlers + +import ( + "fmt" + "net/http" + "strconv" + + "github.com/gorilla/mux" + "github.com/rjNemo/go-micro/products/data" + "github.com/rjNemo/go-micro/products/models" +) + +// swagger:route PUT /products/{id} products product +// Updates a product +// responses: +// 204: productResponse + +// UpdateProduct edit product identified by id +func (p *Products) UpdateProduct(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + id, _ := strconv.Atoi(vars["id"]) + + p.logger.Println("Handle 'PUT' request", id) + // get product from the request + newProd := r.Context().Value(KeyProduct{}).(*models.Product) // cast into a Product + + p.logger.Printf("product: %#v", newProd) + err := data.UpdateProduct(id, newProd) + if err == data.ErrorProductNotFound { + http.Error(w, err.Error(), http.StatusNotFound) + return + } + if err != nil { + errMsg := fmt.Sprintf("something went wrong: %s", err.Error()) + http.Error(w, errMsg, http.StatusInternalServerError) + return + } +} diff --git a/products/handlers/routes.go b/products/handlers/routes.go index 97876f3..fd2f401 100644 --- a/products/handlers/routes.go +++ b/products/handlers/routes.go @@ -20,7 +20,10 @@ func (p *Products) RegisterRoutes(r *mux.Router) { putRouter := r.Methods(http.MethodPut).Subrouter() putRouter.HandleFunc("/{id:[0-9]+}", p.UpdateProduct) putRouter.Use(p.ProductValidationMiddleware) - + // DELETE + deleteRouter := r.Methods(http.MethodDelete).Subrouter() + deleteRouter.HandleFunc("/{id:[0-9]+}", p.DeleteProduct) + // swagger docs opts := middleware.RedocOpts{SpecURL: "/swagger.yaml"} swaggerHandler := middleware.Redoc(opts, nil) getRouter.Handle("/docs", swaggerHandler) diff --git a/swagger.yaml b/swagger.yaml index a80a808..f367f6c 100644 --- a/swagger.yaml +++ b/swagger.yaml @@ -38,9 +38,38 @@ paths: $ref: '#/responses/productsResponse' tags: - products + post: + description: Creates a product + operationId: product + responses: + "201": + $ref: '#/responses/productResponse' + tags: + - products + /products/{id}: + delete: + description: Deletes a product + operationId: product + responses: + "200": + $ref: '#/responses/productResponse' + tags: + - products + put: + description: Updates a product + operationId: product + responses: + "204": + $ref: '#/responses/productResponse' + tags: + - products produces: - application/json responses: + productResponse: + description: product in the response. For go-swagger + schema: + $ref: '#/definitions/Product' productsResponse: description: list of products in the response. For go-swagger schema: