letsgooo/api/petstore.go
2025-03-06 22:00:54 +01:00

127 lines
2.7 KiB
Go

package api
import (
"encoding/json"
"fmt"
"net/http"
"sync"
)
type PetStore struct {
Pets map[int64]Pet
NextId int64
Lock sync.Mutex
}
// Make sure we conform to ServerInterface
var _ ServerInterface = (*PetStore)(nil)
func NewPetStore() *PetStore {
return &PetStore{
Pets: make(map[int64]Pet),
NextId: 1000,
}
}
// sendPetStoreError wraps sending of an error in the Error format, and
// handling the failure to marshal that.
func sendPetStoreError(w http.ResponseWriter, code int, message string) {
petErr := Error{
Code: int32(code),
Message: message,
}
w.WriteHeader(code)
_ = json.NewEncoder(w).Encode(petErr)
}
// FindPets implements all the handlers in the ServerInterface
func (p *PetStore) FindPets(w http.ResponseWriter, r *http.Request, params FindPetsParams) {
p.Lock.Lock()
defer p.Lock.Unlock()
var result []Pet
for _, pet := range p.Pets {
if params.Tags != nil {
// If we have tags, filter pets by tag
for _, t := range *params.Tags {
if pet.Tag != nil && (*pet.Tag == t) {
result = append(result, pet)
}
}
} else {
// Add all pets if we're not filtering
result = append(result, pet)
}
if params.Limit != nil {
l := int(*params.Limit)
if len(result) >= l {
// We're at the limit
break
}
}
}
w.WriteHeader(http.StatusOK)
_ = json.NewEncoder(w).Encode(result)
}
func (p *PetStore) 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 {
sendPetStoreError(w, http.StatusBadRequest, "Invalid format for NewPet")
return
}
// We now have a pet, let's add it to our "database".
// We're always asynchronous, so lock unsafe operations below
p.Lock.Lock()
defer p.Lock.Unlock()
// We handle pets, not NewPets, which have an additional ID field
var pet Pet
pet.Name = newPet.Name
pet.Tag = newPet.Tag
pet.Id = p.NextId
p.NextId++
// Insert into map
p.Pets[pet.Id] = pet
// Now, we have to return the NewPet
w.WriteHeader(http.StatusCreated)
_ = json.NewEncoder(w).Encode(pet)
}
func (p *PetStore) FindPetByID(w http.ResponseWriter, r *http.Request, id int64) {
p.Lock.Lock()
defer p.Lock.Unlock()
pet, found := p.Pets[id]
if !found {
sendPetStoreError(w, http.StatusNotFound, fmt.Sprintf("Could not find pet with ID %d", id))
return
}
w.WriteHeader(http.StatusOK)
_ = json.NewEncoder(w).Encode(pet)
}
func (p *PetStore) DeletePet(w http.ResponseWriter, r *http.Request, id int64) {
p.Lock.Lock()
defer p.Lock.Unlock()
_, found := p.Pets[id]
if !found {
sendPetStoreError(w, http.StatusNotFound, fmt.Sprintf("Could not find pet with ID %d", id))
return
}
delete(p.Pets, id)
w.WriteHeader(http.StatusNoContent)
}