253 lines
5.7 KiB
Go
253 lines
5.7 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
//Go Best practices: https://github.com/golovers/effective-go
|
|
type Item struct {
|
|
ID int64 `json:"id"`
|
|
Name string `json:"name"`
|
|
ValueCents int64 `json:"valueCents"`
|
|
PurchaseCostCents int64 `json:"purchasedCostCents"`
|
|
Aquired time.Time `json:"aquired"`
|
|
Description string `json:"description"`
|
|
Notes string `json:"notes"`
|
|
SoldForCents int64 `json:"soldForCents"`
|
|
SoldTo string `json:"soldTo"`
|
|
Quantity int64 `json:"quantity"`
|
|
Category Category `json:"category"`
|
|
Subcategory Subcategory `json:"subcategory"`
|
|
}
|
|
|
|
func main() {
|
|
http.HandleFunc("/categories", categories)
|
|
//Note: seems adding a trailing slash allows routing URLs like /category/ID#
|
|
//No need for query parameters.
|
|
http.HandleFunc("/category/", category)
|
|
http.HandleFunc("/subcategory/", subcategory)
|
|
|
|
err := http.ListenAndServe(":8088", nil)
|
|
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
}
|
|
|
|
func categories(w http.ResponseWriter, r *http.Request) {
|
|
switch r.Method {
|
|
case "GET":
|
|
getCategoriesHandler(w, r)
|
|
default:
|
|
w.WriteHeader(http.StatusMethodNotAllowed)
|
|
w.Write([]byte("Method not allowed"))
|
|
}
|
|
}
|
|
|
|
func category(w http.ResponseWriter, r *http.Request) {
|
|
switch r.Method {
|
|
case "GET":
|
|
getCategoryHandler(w, r)
|
|
case "POST":
|
|
insertCategoryHandler(w, r)
|
|
case "DELETE":
|
|
deleteCategoryHandler(w, r)
|
|
default:
|
|
w.WriteHeader(http.StatusMethodNotAllowed)
|
|
w.Write([]byte("Method not allowed"))
|
|
}
|
|
}
|
|
|
|
func subcategory(w http.ResponseWriter, r *http.Request) {
|
|
switch r.Method {
|
|
case "POST":
|
|
insertSubcategoryHandler(w, r)
|
|
case "DELETE":
|
|
deleteSubcategoryHandler(w, r)
|
|
default:
|
|
w.WriteHeader(http.StatusMethodNotAllowed)
|
|
w.Write([]byte("Method not allowed"))
|
|
}
|
|
}
|
|
|
|
func deleteSubcategoryHandler(w http.ResponseWriter, r *http.Request) {
|
|
id := strings.TrimPrefix(r.URL.Path, "/subcategory/")
|
|
|
|
value, err := strconv.ParseInt(id, 0, 64)
|
|
|
|
if err != nil {
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
w.Write([]byte(err.Error()))
|
|
return
|
|
}
|
|
|
|
if !deleteSubcategory(value) {
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
w.Write([]byte(fmt.Sprintf("Failed to delete %d", value)))
|
|
return
|
|
}
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
}
|
|
|
|
func getCategoryHandler(w http.ResponseWriter, r *http.Request) {
|
|
id := strings.TrimPrefix(r.URL.Path, "/category/")
|
|
|
|
value, err := strconv.ParseInt(id, 0, 64)
|
|
|
|
if err != nil {
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
w.Write([]byte(err.Error()))
|
|
return
|
|
}
|
|
|
|
category, ok := getCategoryByID(value)
|
|
|
|
if !ok {
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
w.Write([]byte("Failed to get category."))
|
|
return
|
|
}
|
|
|
|
jsonBytes, err := json.Marshal(&category)
|
|
|
|
if err != nil {
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
w.Write([]byte(err.Error()))
|
|
return
|
|
}
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
w.Write(jsonBytes)
|
|
}
|
|
|
|
func deleteCategoryHandler(w http.ResponseWriter, r *http.Request) {
|
|
id := strings.TrimPrefix(r.URL.Path, "/category/")
|
|
|
|
value, err := strconv.ParseInt(id, 0, 64)
|
|
|
|
if err != nil {
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
w.Write([]byte(err.Error()))
|
|
return
|
|
}
|
|
|
|
if !deleteCategory(value) {
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
w.Write([]byte(fmt.Sprintf("Failed to delete %d", value)))
|
|
return
|
|
}
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
}
|
|
|
|
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)
|
|
|
|
if err != nil {
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
w.Write([]byte("Failed to get a list of categories."))
|
|
return
|
|
}
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
w.Write(jsonBytes)
|
|
}
|
|
|
|
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', expected application/json", ct)))
|
|
return
|
|
}
|
|
|
|
bodyBytes, err := ioutil.ReadAll(r.Body)
|
|
|
|
if err != nil {
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
w.Write([]byte("Failed to parse request body"))
|
|
return
|
|
}
|
|
|
|
defer r.Body.Close()
|
|
|
|
var category Category
|
|
|
|
err = json.Unmarshal(bodyBytes, &category)
|
|
|
|
if err != nil {
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
w.Write([]byte("Failed to unmarshal JSON"))
|
|
return
|
|
}
|
|
|
|
id, ok := insertNewCategory(category.Name, category.Subcategories)
|
|
|
|
if !ok {
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
w.Write([]byte("Failed to create the new category."))
|
|
return
|
|
}
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
w.Write([]byte(fmt.Sprintf("New Record: %d", id)))
|
|
}
|
|
|
|
func insertSubcategoryHandler(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', expected application/json", ct)))
|
|
return
|
|
}
|
|
|
|
bodyBytes, err := ioutil.ReadAll(r.Body)
|
|
|
|
if err != nil {
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
w.Write([]byte("Failed to parse request body"))
|
|
return
|
|
}
|
|
|
|
defer r.Body.Close()
|
|
|
|
var subcategory Subcategory
|
|
|
|
err = json.Unmarshal(bodyBytes, &subcategory)
|
|
|
|
if err != nil {
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
w.Write([]byte("Failed to unmarshal JSON"))
|
|
return
|
|
}
|
|
|
|
id, ok := insertSubcategory(subcategory.Name, subcategory.CategoryId)
|
|
|
|
if !ok {
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
w.Write([]byte("Failed to create the new subcategory."))
|
|
return
|
|
}
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
w.Write([]byte(fmt.Sprintf("New Record: %d", id)))
|
|
}
|