You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

331 lines
8.0 KiB

3 years ago
  1. package api
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "io/ioutil"
  7. "log"
  8. "mime/multipart"
  9. "net/http"
  10. "os"
  11. "path/filepath"
  12. "strconv"
  13. "strings"
  14. "git.tovijaeschke.xyz/tovi/JumboPetstore/database"
  15. "git.tovijaeschke.xyz/tovi/JumboPetstore/models"
  16. schema "github.com/Kangaroux/go-map-schema"
  17. "github.com/gorilla/mux"
  18. )
  19. func deserialsePetJson(data []byte) (models.Pet, error) {
  20. var (
  21. petData models.Pet = models.Pet{}
  22. jsonStructureTest map[string]interface{} = make(map[string]interface{})
  23. jsonStructureTestResults *schema.CompareResults
  24. err error
  25. )
  26. // Verify the JSON has the correct structure
  27. json.Unmarshal(data, &jsonStructureTest)
  28. jsonStructureTestResults, err = schema.CompareMapToStruct(
  29. &petData,
  30. jsonStructureTest,
  31. &schema.CompareOpts{
  32. ConvertibleFunc: CanConvert,
  33. TypeNameFunc: schema.DetailedTypeName,
  34. })
  35. if err != nil {
  36. return petData, err
  37. }
  38. if len(jsonStructureTestResults.MismatchedFields) > 0 {
  39. fmt.Println(jsonStructureTestResults.MismatchedFields)
  40. return petData, errors.New("MismatchedFields found when deserializing data")
  41. }
  42. if len(jsonStructureTestResults.MissingFields) > 0 {
  43. fmt.Println(jsonStructureTestResults.MissingFields)
  44. return petData, errors.New("MissingFields found when deserializing data")
  45. }
  46. // Deserialize the JSON into the struct
  47. err = json.Unmarshal(data, &petData)
  48. return petData, err
  49. }
  50. func genericJsonReturn(w http.ResponseWriter, code int, msg, typ string) {
  51. var (
  52. responseJsonMap map[string]interface{}
  53. responseJson []byte
  54. err error
  55. )
  56. responseJsonMap = make(map[string]interface{})
  57. w.WriteHeader(code)
  58. responseJsonMap["code"] = code
  59. responseJsonMap["type"] = typ
  60. responseJsonMap["message"] = msg
  61. responseJson, err = json.MarshalIndent(responseJsonMap, "", " ")
  62. if err != nil {
  63. log.Printf("Error occured creating response: %s\n", err.Error())
  64. }
  65. w.Write(responseJson)
  66. }
  67. func PetHandlerCreateUpdate(w http.ResponseWriter, r *http.Request) {
  68. var (
  69. requestBody []byte
  70. petData models.Pet
  71. returnJson []byte
  72. err error
  73. )
  74. log.Printf("Pet handler recieved %s request", r.Method)
  75. requestBody, err = ioutil.ReadAll(r.Body)
  76. if err != nil {
  77. log.Printf("Error encountered reading POST body: %s\n", err.Error())
  78. genericJsonReturn(w, 500, "An error occured", "unknown")
  79. return
  80. }
  81. petData, err = deserialsePetJson(requestBody)
  82. if err != nil {
  83. log.Printf("Invalid data provided to pet POST API: %s\n", err.Error())
  84. genericJsonReturn(w, 405, "Invalid data", "unknown")
  85. return
  86. }
  87. switch r.Method {
  88. case "POST":
  89. petData, err = database.CreatePet(petData)
  90. if err != nil {
  91. panic(err)
  92. }
  93. break
  94. case "PUT":
  95. petData, err = database.UpdatePet(petData)
  96. if err != nil {
  97. panic(err)
  98. }
  99. break
  100. }
  101. returnJson, err = json.MarshalIndent(petData, "", " ")
  102. if err != nil {
  103. log.Printf("Error encountered when creating pet record: %s\n", err.Error())
  104. w.WriteHeader(http.StatusInternalServerError)
  105. w.Write([]byte("500 - An error has occured\n"))
  106. return
  107. }
  108. // Return updated json
  109. w.WriteHeader(http.StatusOK)
  110. w.Write(returnJson)
  111. }
  112. func PetHandlerId(w http.ResponseWriter, r *http.Request) {
  113. var (
  114. petData models.Pet
  115. urlVars map[string]string
  116. returnJson []byte
  117. notFoundJson map[string]interface{} = make(map[string]interface{})
  118. id_str string
  119. id int
  120. ok bool
  121. err error
  122. )
  123. urlVars = mux.Vars(r)
  124. id_str, ok = urlVars["petId"]
  125. if !ok {
  126. log.Printf("Error encountered getting id\n")
  127. w.WriteHeader(http.StatusInternalServerError)
  128. w.Write([]byte("500 - An error has occured\n"))
  129. return
  130. }
  131. id, err = strconv.Atoi(id_str)
  132. if err != nil {
  133. log.Printf("Error encountered converting id to string: %s\n", err.Error())
  134. w.WriteHeader(http.StatusInternalServerError)
  135. w.Write([]byte("500 - An error has occured\n"))
  136. return
  137. }
  138. petData = database.GetPetById(id)
  139. if petData.Id == 0 {
  140. log.Printf("Could not find pet with id %d\n", id)
  141. w.WriteHeader(http.StatusNotFound)
  142. notFoundJson["code"] = 404
  143. notFoundJson["type"] = "unknown"
  144. notFoundJson["message"] = "not found"
  145. returnJson, err = json.MarshalIndent(notFoundJson, "", " ")
  146. w.Write(returnJson)
  147. return
  148. }
  149. switch r.Method {
  150. case "GET":
  151. returnJson, err = json.MarshalIndent(petData, "", " ")
  152. if err != nil {
  153. log.Printf("Error encountered when creating pet record: %s\n", err.Error())
  154. w.WriteHeader(http.StatusInternalServerError)
  155. w.Write([]byte("500 - An error has occured\n"))
  156. return
  157. }
  158. // Return updated json
  159. w.WriteHeader(http.StatusOK)
  160. w.Write(returnJson)
  161. break
  162. case "POST":
  163. err = r.ParseForm()
  164. if err != nil {
  165. log.Printf("Error encountered parsing form: %s\n", err.Error())
  166. w.WriteHeader(http.StatusInternalServerError)
  167. w.Write([]byte("500 - An error has occured\n"))
  168. return
  169. }
  170. if r.FormValue("name") != "" {
  171. petData.Name = r.FormValue("name")
  172. }
  173. if r.FormValue("status") != "" {
  174. petData.Status = r.FormValue("status")
  175. }
  176. _, err = database.UpdatePet(petData)
  177. if err != nil {
  178. log.Printf("Error updating pet: %s\n", err.Error())
  179. w.WriteHeader(http.StatusInternalServerError)
  180. w.Write([]byte("500 - An error has occured\n"))
  181. return
  182. }
  183. break
  184. case "DELETE":
  185. log.Printf("Marking pet %d as deleted\n", id)
  186. database.DeletePet(petData)
  187. w.WriteHeader(http.StatusOK)
  188. notFoundJson["code"] = 200
  189. notFoundJson["type"] = "unknown"
  190. notFoundJson["message"] = id_str
  191. returnJson, err = json.MarshalIndent(notFoundJson, "", " ")
  192. w.Write(returnJson)
  193. break
  194. }
  195. }
  196. func PetHandlerFindByStatus(w http.ResponseWriter, r *http.Request) {
  197. var (
  198. status string
  199. petData []models.Pet
  200. returnJson []byte
  201. err error
  202. )
  203. status = r.URL.Query().Get("status")
  204. if status != "available" && status != "pending" && status != "sold" {
  205. log.Printf("Invalid status provided to /pet/findByStatus")
  206. w.WriteHeader(http.StatusInternalServerError)
  207. w.Write([]byte("500 - An error has occured\n"))
  208. return
  209. }
  210. petData, err = database.GetPetsByStatus(status)
  211. if err != nil {
  212. log.Printf("An error occured in GetPetsByStatus")
  213. w.WriteHeader(http.StatusInternalServerError)
  214. w.Write([]byte("500 - An error has occured\n"))
  215. return
  216. }
  217. returnJson, err = json.MarshalIndent(petData, "", " ")
  218. if err != nil {
  219. log.Printf("An error occured while serializing pet data to JSON")
  220. w.WriteHeader(http.StatusInternalServerError)
  221. w.Write([]byte("500 - An error has occured\n"))
  222. return
  223. }
  224. w.Write(returnJson)
  225. }
  226. func PetHandlerUploadImage(w http.ResponseWriter, r *http.Request) {
  227. var (
  228. urlVars map[string]string
  229. file multipart.File
  230. handler *multipart.FileHeader
  231. tempFile *os.File
  232. nameSplit []string
  233. fileBytes []byte
  234. id_str string
  235. id int
  236. ok bool
  237. err error
  238. )
  239. urlVars = mux.Vars(r)
  240. id_str, ok = urlVars["petId"]
  241. if !ok {
  242. log.Printf("Error encountered getting id\n")
  243. w.WriteHeader(http.StatusInternalServerError)
  244. w.Write([]byte("500 - An error has occured\n"))
  245. return
  246. }
  247. id, err = strconv.Atoi(id_str)
  248. if err != nil {
  249. log.Printf("Error encountered converting id to string: %s\n", err.Error())
  250. w.WriteHeader(http.StatusInternalServerError)
  251. w.Write([]byte("500 - An error has occured\n"))
  252. return
  253. }
  254. fmt.Println(id)
  255. // Upload 10Mb files
  256. r.ParseMultipartForm(10 << 20)
  257. file, handler, err = r.FormFile("file")
  258. if err != nil {
  259. log.Printf("Error retrieving file: %s\n", err.Error())
  260. w.WriteHeader(http.StatusInternalServerError)
  261. w.Write([]byte("500 - An error has occured\n"))
  262. return
  263. }
  264. defer file.Close()
  265. nameSplit = strings.Split(handler.Filename, ".")
  266. tempFile, err = ioutil.TempFile("./uploads", "upload-*."+nameSplit[len(nameSplit)-1])
  267. if err != nil {
  268. fmt.Println(err)
  269. return
  270. }
  271. defer tempFile.Close()
  272. fileBytes, err = ioutil.ReadAll(file)
  273. if err != nil {
  274. fmt.Println(err)
  275. return
  276. }
  277. tempFile.Write(fileBytes)
  278. err = database.AddPhotoToPet(id, filepath.Base(tempFile.Name()))
  279. if err != nil {
  280. fmt.Println(err)
  281. return
  282. }
  283. fmt.Fprintf(w, "Successfully Uploaded File\n")
  284. }