Category data now includes their subcategories. Categories can now be requested by ID in a prettier way.

This commit is contained in:
2021-09-09 11:34:06 -05:00
parent 20a6365159
commit 871484a8e5
4 changed files with 147 additions and 57 deletions
+34 -46
View File
@@ -1,18 +1,18 @@
package main
import (
"database/sql"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strconv"
"strings"
"time"
)
//Go Best practices: https://github.com/golovers/effective-go
type Item struct {
Id int32 `json:"id"`
ID int32 `json:"id"`
Name int32 `json:"name"`
ValueCents int32 `json:"valueCents"`
PurchaseCostCents int32 `json:"purchasedCostCents"`
@@ -27,8 +27,11 @@ type Item struct {
func main() {
http.HandleFunc("/categories", categories)
http.HandleFunc("/category", category)
err := http.ListenAndServe(":8080", nil)
//Note: seems adding a trailing slash allows routing URLs like /category/ID#
//No need for query parameters.
http.HandleFunc("/category/", category)
err := http.ListenAndServe(":8088", nil)
if err != nil {
panic(err)
@@ -39,7 +42,7 @@ func main() {
func categories(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case "GET":
getCategories(w, r)
getCategoriesHandler(w, r)
default:
w.WriteHeader(http.StatusMethodNotAllowed)
w.Write([]byte("Method not allowed"))
@@ -49,19 +52,19 @@ func categories(w http.ResponseWriter, r *http.Request) {
func category(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case "GET":
getCategory(w, r)
getCategoryHandler(w, r)
case "POST":
insertCategory(w, r)
insertCategoryHandler(w, r)
case "DELETE":
deleteCategory(w, r)
deleteCategoryHandler(w, r)
default:
w.WriteHeader(http.StatusMethodNotAllowed)
w.Write([]byte("Method not allowed"))
}
}
func getCategory(w http.ResponseWriter, r *http.Request) {
id := r.URL.Query().Get("id")
func getCategoryHandler(w http.ResponseWriter, r *http.Request) {
id := strings.TrimPrefix(r.URL.Path, "/category/")
value, err := strconv.ParseInt(id, 0, 64)
@@ -71,19 +74,11 @@ func getCategory(w http.ResponseWriter, r *http.Request) {
return
}
db := getSQLConnection()
category, ok := getCategoryByID(value)
defer db.Close()
var category Category
if err := db.QueryRow("SELECT * FROM category WHERE category_id = $1;", value).Scan(&category.Id, &category.Name); err != nil {
if err == sql.ErrNoRows {
w.Write([]byte("No rows found"))
return
}
w.Write([]byte(err.Error()))
if !ok {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte("Failed to get category."))
return
}
@@ -99,8 +94,8 @@ func getCategory(w http.ResponseWriter, r *http.Request) {
w.Write(jsonBytes)
}
func deleteCategory(w http.ResponseWriter, r *http.Request) {
id := r.URL.Query().Get("id")
func deleteCategoryHandler(w http.ResponseWriter, r *http.Request) {
id := strings.TrimPrefix(r.URL.Path, "/category/")
value, err := strconv.ParseInt(id, 0, 64)
@@ -110,24 +105,23 @@ func deleteCategory(w http.ResponseWriter, r *http.Request) {
return
}
db := getSQLConnection()
defer db.Close()
_, err = db.Exec("DELETE FROM category WHERE category_id = $1;", value)
if err != nil {
if !deleteCategory(value) {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(err.Error()))
w.Write([]byte(fmt.Sprintf("Failed to delete %d", value)))
return
}
w.WriteHeader(http.StatusOK)
w.Write([]byte(fmt.Sprintf("Deleted category '%d'.", value)))
}
func getCategories(w http.ResponseWriter, r *http.Request) {
categories := getAllCategories()
func getCategoriesHandler(w http.ResponseWriter, r *http.Request) {
categories, ok := getAllCategories()
if !ok {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte("Failed to fetch a list of categories."))
return
}
jsonBytes, err := json.Marshal(categories)
@@ -141,12 +135,12 @@ func getCategories(w http.ResponseWriter, r *http.Request) {
w.Write(jsonBytes)
}
func insertCategory(w http.ResponseWriter, r *http.Request) {
func insertCategoryHandler(w http.ResponseWriter, r *http.Request) {
ct := r.Header.Get("content-type")
if ct != "application/json" {
w.WriteHeader(http.StatusUnsupportedMediaType)
w.Write([]byte(fmt.Sprintf("Unsupported media type '%s'", ct)))
w.Write([]byte(fmt.Sprintf("Unsupported media type '%s', expected application/json", ct)))
return
}
@@ -170,17 +164,11 @@ func insertCategory(w http.ResponseWriter, r *http.Request) {
return
}
db := getSQLConnection()
id, ok := insertNewCategory(category.Name)
defer db.Close()
id := 0
err = db.QueryRow("INSERT INTO category (category_name) VALUES ($1) RETURNING category_id;", category.Name).Scan(&id)
if err != nil {
if !ok {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error()))
w.Write([]byte("Failed to create the new category."))
return
}