valiation and logging
This commit is contained in:
parent
fdbefeffe2
commit
cb500b7558
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)},
|
||||
},
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue