From 48d32bc05b780bbc31184a848747c7c69cff1a4b Mon Sep 17 00:00:00 2001 From: jake Date: Sun, 28 Feb 2021 21:59:18 -0600 Subject: [PATCH] complex bodies now validatable --- prehandler.go | 27 +++++++++++++++++---------- prehandler_test.go | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 10 deletions(-) diff --git a/prehandler.go b/prehandler.go index 799da6b..5048300 100644 --- a/prehandler.go +++ b/prehandler.go @@ -73,7 +73,7 @@ func validate(val Validate, query url.Values, body interface{}, path map[string] } if val.Body.Initialized() && val.Body.kind != KindFile { - err := validateBody(&val.Body, body) + err := validateBody("body", &val.Body, body) if err != nil { return err } @@ -96,42 +96,49 @@ func validate(val Validate, query url.Values, body interface{}, path map[string] return nil } -func validateBody(field *Field, body interface{}) error { +func validateBody(name string, field *Field, body interface{}) error { switch v := body.(type) { case nil: if field.required != nil && *field.required { - return fmt.Errorf("body validation failed for field %v: %v", field, errRequired) + return fmt.Errorf("body validation failed for field %v: %v", name, errRequired) } case string: if err := field.Validate(v); err != nil { - return fmt.Errorf("body validation failed: %v", err.Error()) + return fmt.Errorf("body validation failed for field %v: %v", name, err.Error()) } case bool: if err := field.Validate(v); err != nil { - return fmt.Errorf("body validation failed: %v", err.Error()) + return fmt.Errorf("body validation failed for field %v: %v", name, err.Error()) } case float64: if field.kind == KindInteger { // JSON doesn't have integers, so Go treats these fields as float64. // Need to convert to integer before validating it. if v != float64(int64(v)) { - return fmt.Errorf("body validation failed for field %v: %v", field, errWrongType) + return fmt.Errorf("body validation failed for field %v: %v", name, errWrongType) } if err := field.Validate(int(v)); err != nil { - return fmt.Errorf("body validation failed: %v", err.Error()) + return fmt.Errorf("body validation failed for field %v: %v", name, err.Error()) } } else { if err := field.Validate(v); err != nil { - return fmt.Errorf("body validation failed: %v", err.Error()) + return fmt.Errorf("body validation failed for field %v: %v", name, err.Error()) } } case []interface{}: if err := field.Validate(v); err != nil { - return fmt.Errorf("body validation failed: %v", err.Error()) + return fmt.Errorf("body validation failed for field %v: %v", name, err.Error()) + } + if field.arr != nil { + for i, item := range v { + if err := validateBody(fmt.Sprintf("%v[%v]", name, i), field.arr, item); err != nil { + return err + } + } } case map[string]interface{}: for name, field := range field.obj { - if err := validateBody(&field, v[name]); err != nil { + if err := validateBody(name, &field, v[name]); err != nil { return err } } diff --git a/prehandler_test.go b/prehandler_test.go index 40ae232..30799d9 100644 --- a/prehandler_test.go +++ b/prehandler_test.go @@ -304,6 +304,38 @@ func TestBodyValidation(t *testing.T) { }, Input: `{"obj2":{"inner":"not a number"}}`, Expected: 400, + }, { + Schema: map[string]Field{ + "arr1": Array().Items(Number()), + }, + Input: `{"arr1":[1]}`, + Expected: 200, + }, { + Schema: map[string]Field{ + "arr2": Array().Items(Number()), + }, + Input: `{"arr2":["a"]}`, + Expected: 400, + }, { + Schema: map[string]Field{ + "complex1": Object(map[string]Field{ + "array": Array().Required().Items(Object(map[string]Field{ + "id": Number().Required(), + })), + }).Required(), + }, + Input: `{"complex1":{"array":[{"id":1}]}}`, + Expected: 200, + }, { + Schema: map[string]Field{ + "complex2": Object(map[string]Field{ + "array": Array().Required().Items(Object(map[string]Field{ + "id": Number().Required(), + })), + }).Required(), + }, + Input: `{"complex2":{"array":[{"id":"a"}]}}`, + Expected: 400, }, }