mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Add nil checks to HTTP request validation dispatch (#44371)
Signed-off-by: Igor Suleymanov <igor.suleymanov@grafana.com>
This commit is contained in:
parent
a7423d8760
commit
fdeaf7a5c4
@ -26,14 +26,27 @@ type Validator interface {
|
||||
}
|
||||
|
||||
func validate(obj interface{}) error {
|
||||
// First check if obj is nil, because we cannot validate those.
|
||||
if obj == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Second, check if obj has a nil interface value.
|
||||
// This is to prevent panics when obj is an instance of uninitialised struct pointer / interface.
|
||||
t := reflect.TypeOf(obj)
|
||||
v := reflect.ValueOf(obj)
|
||||
|
||||
if v.Kind() == reflect.Ptr && v.IsNil() {
|
||||
return nil
|
||||
}
|
||||
|
||||
// If type has a Validate() method - use that
|
||||
if validator, ok := obj.(Validator); ok {
|
||||
return validator.Validate()
|
||||
}
|
||||
|
||||
// Otherwise, use reflection to match `binding:"Required"` struct field tags.
|
||||
// Resolve all pointers and interfaces, until we get a concrete type.
|
||||
t := reflect.TypeOf(obj)
|
||||
v := reflect.ValueOf(obj)
|
||||
for v.Kind() == reflect.Interface || v.Kind() == reflect.Ptr {
|
||||
t = t.Elem()
|
||||
v = v.Elem()
|
||||
|
@ -50,8 +50,22 @@ func (sv StructWithValidation) Validate() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type StructWithPointerValidation struct {
|
||||
A int
|
||||
}
|
||||
|
||||
func (sv *StructWithPointerValidation) Validate() error {
|
||||
if sv.A < 10 {
|
||||
return errors.New("too small")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestValidationSuccess(t *testing.T) {
|
||||
var nilInterface *StructWithPointerValidation
|
||||
|
||||
for _, x := range []interface{}{
|
||||
nil,
|
||||
42,
|
||||
"foo",
|
||||
struct{ A int }{},
|
||||
@ -65,6 +79,8 @@ func TestValidationSuccess(t *testing.T) {
|
||||
StructWithStruct{StructWithInt{3}},
|
||||
StructWithStructPointer{&StructWithInt{3}},
|
||||
StructWithValidation{42},
|
||||
&StructWithPointerValidation{42},
|
||||
nilInterface,
|
||||
} {
|
||||
if err := validate(x); err != nil {
|
||||
t.Error("Validation failed:", x, err)
|
||||
@ -93,6 +109,7 @@ func TestValidationFailure(t *testing.T) {
|
||||
StructWithStructPointer{},
|
||||
StructWithStructPointer{&StructWithInt{}},
|
||||
StructWithValidation{2},
|
||||
&StructWithPointerValidation{2},
|
||||
} {
|
||||
if err := validate(x); err == nil {
|
||||
t.Error("Validation should fail:", i, x)
|
||||
|
Loading…
Reference in New Issue
Block a user