/
handler.go
140 lines (118 loc) · 3.32 KB
/
handler.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
//go:generate go run github.com/deepmap/oapi-codegen/cmd/oapi-codegen --config=cfg.yaml ./PetStore.yaml
package petstore
import (
"encoding/json"
"errors"
"fmt"
"log"
"net/http"
"sync"
"github.com/ashwinrs/gos/internal/models"
"gorm.io/gorm"
)
type PetStoreHandler struct {
NextId int64
Lock sync.Mutex
db *gorm.DB
}
// Make sure we conform to ServerInterface
var _ ServerInterface = (*PetStoreHandler)(nil)
func NewPetStoreHandler(db *gorm.DB) *PetStoreHandler {
return &PetStoreHandler{
NextId: 1000,
db: db,
}
}
// GetPets implements all the handlers in the ServerInterface
func (p *PetStoreHandler) GetPets(w http.ResponseWriter, r *http.Request, params GetPetsParams) {
var queryResult []models.PetEntity
limit := 10
if params.Limit != nil {
limit = int(*params.Limit)
}
if params.Tags != nil {
if result := p.db.Limit(limit).Where("tag IN ?", *params.Tags).Find(&queryResult); result.Error != nil {
log.Println(result.Error)
}
} else {
if result := p.db.Limit(limit).Find(&queryResult); result.Error != nil {
log.Println(result.Error)
return
}
}
response := make([]Pet, len(queryResult))
for i, pet := range queryResult {
response[i] = Pet{
Id: pet.Id,
Name: pet.Name,
Tag: pet.Tag,
}
}
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(response)
}
func (p *PetStoreHandler) AddPet(w http.ResponseWriter, r *http.Request) {
// We expect a NewPet object in the request body.
var newPet NewPet
if err := json.NewDecoder(r.Body).Decode(&newPet); err != nil {
sendPetStoreHandlerError(w, http.StatusBadRequest, "Invalid format for NewPet")
return
}
// We handle pets, not NewPets, which have an additional ID field
var pet models.PetEntity
pet.Name = newPet.Name
pet.Tag = newPet.Tag
pet.Id = p.NextId
p.NextId = p.NextId + 1
if result := p.db.Create(&pet); result.Error != nil {
log.Println(result.Error)
}
response := Pet{
Id: pet.Id,
Name: pet.Name,
Tag: pet.Tag,
}
// Now, we have to return the NewPet
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(response)
}
func (p *PetStoreHandler) FindPetByID(w http.ResponseWriter, r *http.Request, id int64) {
var pet models.PetEntity
// check if it exists
result := p.db.First(&pet, id)
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
sendPetStoreHandlerError(w, http.StatusNotFound, fmt.Sprintf("Could not find pet with ID %d", id))
return
}
response := Pet{
Id: pet.Id,
Name: pet.Name,
Tag: pet.Tag,
}
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(response)
}
func (p *PetStoreHandler) DeletePet(w http.ResponseWriter, r *http.Request, id int64) {
var pet models.PetEntity
// check if it exists
result := p.db.First(&pet, id)
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
sendPetStoreHandlerError(w, http.StatusNotFound, fmt.Sprintf("Could not find pet with ID %d", id))
return
}
// delete if it does exist
if result = p.db.Delete(&pet, id); result.Error != nil {
log.Println(result.Error)
}
w.WriteHeader(http.StatusNoContent)
}
// This function wraps sending of an error in the Error format, and
// handling the failure to marshal that.
func sendPetStoreHandlerError(w http.ResponseWriter, code int, message string) {
petErr := Error{
Code: int32(code),
Message: message,
}
w.WriteHeader(code)
json.NewEncoder(w).Encode(petErr)
}