valiation and logging

This commit is contained in:
Erik Winter 2024-09-09 07:56:01 +02:00
parent fdbefeffe2
commit cb500b7558
3 changed files with 53 additions and 24 deletions

View File

@ -33,7 +33,9 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
if r.Header.Get("Authorization") != fmt.Sprintf("Bearer %s", s.apiKey) {
http.Error(w, `{"error":"not authorized"}`, http.StatusUnauthorized)
msg := "not authorized"
http.Error(w, fmtError(msg), http.StatusUnauthorized)
s.logger.Info(msg)
return
}
@ -46,7 +48,9 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
case head == "sync" && r.Method == http.MethodPost:
s.SyncPost(w, r)
default:
http.Error(w, `{"error":"not found"}`, http.StatusNotFound)
msg := "not found"
http.Error(w, fmtError(msg), http.StatusNotFound)
s.logger.Info(msg)
}
}
@ -56,20 +60,26 @@ func (s *Server) SyncGet(w http.ResponseWriter, r *http.Request) {
if tsStr != "" {
var err error
if timestamp, err = time.Parse(time.RFC3339, tsStr); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
msg := err.Error()
http.Error(w, fmtError(msg), http.StatusBadRequest)
s.logger.Info(msg)
return
}
}
items, err := s.syncer.Updated(timestamp)
if err != nil {
http.Error(w, fmtError(err), http.StatusInternalServerError)
msg := err.Error()
http.Error(w, fmtError(msg), http.StatusInternalServerError)
s.logger.Error(msg)
return
}
body, err := json.Marshal(items)
if err != nil {
http.Error(w, fmtError(err), http.StatusInternalServerError)
msg := err.Error()
http.Error(w, fmtError(msg), http.StatusInternalServerError)
s.logger.Error(msg)
return
}
@ -80,33 +90,45 @@ func (s *Server) SyncGet(w http.ResponseWriter, r *http.Request) {
func (s *Server) SyncPost(w http.ResponseWriter, r *http.Request) {
body, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, fmtError(err), http.StatusBadRequest)
msg := err.Error()
http.Error(w, fmtError(msg), http.StatusBadRequest)
s.logger.Info(msg)
return
}
defer r.Body.Close()
var items []Item
if err := json.Unmarshal(body, &items); err != nil {
http.Error(w, fmtError(err), http.StatusBadRequest)
msg := err.Error()
http.Error(w, fmtError(msg), http.StatusBadRequest)
s.logger.Info(msg)
return
}
for _, item := range items {
if item.ID == "" {
http.Error(w, `{"error":"item without an id"}`, http.StatusBadRequest)
msg := "item without an id"
http.Error(w, fmtError(msg), http.StatusBadRequest)
s.logger.Info(msg)
return
}
if item.Kind == "" {
http.Error(w, fmt.Sprintf(`{"error":"item %s does not have a kind"}`, item.ID), http.StatusBadRequest)
msg := fmt.Sprintf("item %s does not have a kind", item.ID)
http.Error(w, fmtError(msg), http.StatusBadRequest)
s.logger.Info(msg)
return
}
if item.Body == "" {
http.Error(w, fmt.Sprintf(`{"error":"item %s does not have a body"}`, item.ID), http.StatusBadRequest)
msg := fmt.Sprintf(`{"error":"item %s does not have a body"}`, item.ID)
http.Error(w, msg, http.StatusBadRequest)
s.logger.Info(msg)
return
}
item.Updated = time.Now()
if err := s.syncer.Update(item); err != nil {
http.Error(w, fmtError(err), http.StatusInternalServerError)
msg := err.Error()
http.Error(w, fmtError(msg), http.StatusInternalServerError)
s.logger.Error(msg)
return
}
}
@ -132,6 +154,6 @@ func Index(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, `{"status":"ok"}`)
}
func fmtError(err error) string {
return fmt.Sprintf(`{"error":%q}`, err.Error())
func fmtError(msg string) string {
return fmt.Sprintf(`{"error":%q}`, msg)
}

View File

@ -55,7 +55,7 @@ func TestSyncGet(t *testing.T) {
now := time.Now()
mem := NewMemory()
items := []Syncable{
items := []Item{
{ID: "id-0", Updated: now.Add(-10 * time.Minute)},
{ID: "id-1", Updated: now.Add(-5 * time.Minute)},
{ID: "id-2", Updated: now.Add(time.Minute)},
@ -74,7 +74,7 @@ func TestSyncGet(t *testing.T) {
name string
ts time.Time
expStatus int
expItems []Syncable
expItems []Item
}{
{
name: "full",
@ -85,7 +85,7 @@ func TestSyncGet(t *testing.T) {
name: "normal",
ts: now.Add(-6 * time.Minute),
expStatus: http.StatusOK,
expItems: []Syncable{items[1], items[2]},
expItems: []Item{items[1], items[2]},
},
} {
t.Run(tc.name, func(t *testing.T) {
@ -101,7 +101,7 @@ func TestSyncGet(t *testing.T) {
if res.Result().StatusCode != tc.expStatus {
t.Errorf("exp %v, got %v", tc.expStatus, res.Result().StatusCode)
}
var actItems []Syncable
var actItems []Item
actBody, err := io.ReadAll(res.Result().Body)
if err != nil {
t.Errorf("exp nil, got %v", err)
@ -135,25 +135,32 @@ func TestSyncPost(t *testing.T) {
name string
reqBody []byte
expStatus int
expItems []Syncable
expItems []Item
}{
{
name: "empty",
expStatus: http.StatusBadRequest,
},
{
name: "invalid",
name: "invalid json",
reqBody: []byte(`{"fail}`),
expStatus: http.StatusBadRequest,
},
{
name: "invalid item",
reqBody: []byte(`[
{"id":"id-1","kind":"test","updated":"2024-09-06T08:00:00Z"},
]`),
expStatus: http.StatusBadRequest,
},
{
name: "normal",
reqBody: []byte(`[
{"ID":"id-1","Updated":"2024-09-06T08:00:00Z","Deleted":false,"Item":""},
{"ID":"id-2","Updated":"2024-09-06T08:12:00Z","Deleted":false,"Item":""}
{"id":"id-1","kind":"test","updated":"2024-09-06T08:00:00Z","deleted":false,"body":"item"},
{"id":"id-2","kind":"test","updated":"2024-09-06T08:12:00Z","deleted":false,"body":"item2"}
]`),
expStatus: http.StatusNoContent,
expItems: []Syncable{
expItems: []Item{
{ID: "id-1", Updated: time.Date(2024, 9, 6, 8, 0, 0, 0, time.UTC)},
{ID: "id-2", Updated: time.Date(2024, 9, 6, 12, 0, 0, 0, time.UTC)},
},

View File

@ -20,7 +20,7 @@ func TestMemoryItem(t *testing.T) {
}
t.Log("add one")
t1 := NewSyncable("test")
t1 := NewItem("test")
if actErr := mem.Update(t1); actErr != nil {
t.Errorf("exp nil, got %v", actErr)
}
@ -38,7 +38,7 @@ func TestMemoryItem(t *testing.T) {
before := time.Now()
t.Log("add second")
t2 := NewSyncable("test 2")
t2 := NewItem("test 2")
if actErr := mem.Update(t2); actErr != nil {
t.Errorf("exp nil, got %v", actErr)
}