param_validator.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. package aws
  2. import (
  3. "fmt"
  4. "reflect"
  5. "strings"
  6. "github.com/ks3sdklib/aws-sdk-go/internal/apierr"
  7. )
  8. // ValidateParameters is a request handler to validate the input parameters.
  9. // Validating parameters only has meaning if done prior to the request being sent.
  10. func ValidateParameters(r *Request) {
  11. if r.ParamsFilled() {
  12. v := validator{errors: []string{}}
  13. v.validateAny(reflect.ValueOf(r.Params), "")
  14. if count := len(v.errors); count > 0 {
  15. format := "%d validation errors:\n- %s"
  16. msg := fmt.Sprintf(format, count, strings.Join(v.errors, "\n- "))
  17. r.Error = apierr.New("InvalidParameter", msg, nil)
  18. }
  19. }
  20. }
  21. // A validator validates values. Collects validations errors which occurs.
  22. type validator struct {
  23. errors []string
  24. }
  25. // validateAny will validate any struct, slice or map type. All validations
  26. // are also performed recursively for nested types.
  27. func (v *validator) validateAny(value reflect.Value, path string) {
  28. value = reflect.Indirect(value)
  29. if !value.IsValid() {
  30. return
  31. }
  32. switch value.Kind() {
  33. case reflect.Struct:
  34. v.validateStruct(value, path)
  35. case reflect.Slice:
  36. for i := 0; i < value.Len(); i++ {
  37. v.validateAny(value.Index(i), path+fmt.Sprintf("[%d]", i))
  38. }
  39. case reflect.Map:
  40. for _, n := range value.MapKeys() {
  41. v.validateAny(value.MapIndex(n), path+fmt.Sprintf("[%q]", n.String()))
  42. }
  43. }
  44. }
  45. // validateStruct will validate the struct value's fields. If the structure has
  46. // nested types those types will be validated also.
  47. func (v *validator) validateStruct(value reflect.Value, path string) {
  48. prefix := "."
  49. if path == "" {
  50. prefix = ""
  51. }
  52. for i := 0; i < value.Type().NumField(); i++ {
  53. f := value.Type().Field(i)
  54. if strings.ToLower(f.Name[0:1]) == f.Name[0:1] {
  55. continue
  56. }
  57. fvalue := value.FieldByName(f.Name)
  58. notset := false
  59. notval := false
  60. if f.Tag.Get("required") != "" {
  61. switch fvalue.Kind() {
  62. case reflect.Ptr:
  63. if fvalue.IsNil() {
  64. notset = true
  65. } else {
  66. elem := fvalue.Elem()
  67. if elem.Kind() == reflect.String && elem.Len() == 0 {
  68. notval = true
  69. }
  70. }
  71. case reflect.Slice, reflect.Map:
  72. if fvalue.IsNil() {
  73. notset = true
  74. }
  75. default:
  76. if !fvalue.IsValid() {
  77. notset = true
  78. }
  79. }
  80. }
  81. if notset {
  82. msg := "missing required parameter: " + path + prefix + f.Name
  83. v.errors = append(v.errors, msg)
  84. } else if notval {
  85. msg := "input member " + path + prefix + f.Name + " must not be empty"
  86. v.errors = append(v.errors, msg)
  87. } else {
  88. v.validateAny(fvalue, path+prefix+f.Name)
  89. }
  90. }
  91. }