query.go 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. package runtime
  2. import (
  3. "fmt"
  4. "net/url"
  5. "reflect"
  6. "strconv"
  7. "strings"
  8. "time"
  9. "github.com/golang/protobuf/proto"
  10. "github.com/grpc-ecosystem/grpc-gateway/utilities"
  11. "google.golang.org/grpc/grpclog"
  12. )
  13. // PopulateQueryParameters populates "values" into "msg".
  14. // A value is ignored if its key starts with one of the elements in "filter".
  15. func PopulateQueryParameters(msg proto.Message, values url.Values, filter *utilities.DoubleArray) error {
  16. for key, values := range values {
  17. fieldPath := strings.Split(key, ".")
  18. if filter.HasCommonPrefix(fieldPath) {
  19. continue
  20. }
  21. if err := populateFieldValueFromPath(msg, fieldPath, values); err != nil {
  22. return err
  23. }
  24. }
  25. return nil
  26. }
  27. // PopulateFieldFromPath sets a value in a nested Protobuf structure.
  28. // It instantiates missing protobuf fields as it goes.
  29. func PopulateFieldFromPath(msg proto.Message, fieldPathString string, value string) error {
  30. fieldPath := strings.Split(fieldPathString, ".")
  31. return populateFieldValueFromPath(msg, fieldPath, []string{value})
  32. }
  33. func populateFieldValueFromPath(msg proto.Message, fieldPath []string, values []string) error {
  34. m := reflect.ValueOf(msg)
  35. if m.Kind() != reflect.Ptr {
  36. return fmt.Errorf("unexpected type %T: %v", msg, msg)
  37. }
  38. var props *proto.Properties
  39. m = m.Elem()
  40. for i, fieldName := range fieldPath {
  41. isLast := i == len(fieldPath)-1
  42. if !isLast && m.Kind() != reflect.Struct {
  43. return fmt.Errorf("non-aggregate type in the mid of path: %s", strings.Join(fieldPath, "."))
  44. }
  45. var f reflect.Value
  46. var err error
  47. f, props, err = fieldByProtoName(m, fieldName)
  48. if err != nil {
  49. return err
  50. } else if !f.IsValid() {
  51. grpclog.Printf("field not found in %T: %s", msg, strings.Join(fieldPath, "."))
  52. return nil
  53. }
  54. switch f.Kind() {
  55. case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64, reflect.String, reflect.Uint32, reflect.Uint64:
  56. if !isLast {
  57. return fmt.Errorf("unexpected nested field %s in %s", fieldPath[i+1], strings.Join(fieldPath[:i+1], "."))
  58. }
  59. m = f
  60. case reflect.Slice:
  61. // TODO(yugui) Support []byte
  62. if !isLast {
  63. return fmt.Errorf("unexpected repeated field in %s", strings.Join(fieldPath, "."))
  64. }
  65. return populateRepeatedField(f, values, props)
  66. case reflect.Ptr:
  67. if f.IsNil() {
  68. m = reflect.New(f.Type().Elem())
  69. f.Set(m.Convert(f.Type()))
  70. }
  71. m = f.Elem()
  72. continue
  73. case reflect.Struct:
  74. m = f
  75. continue
  76. default:
  77. return fmt.Errorf("unexpected type %s in %T", f.Type(), msg)
  78. }
  79. }
  80. switch len(values) {
  81. case 0:
  82. return fmt.Errorf("no value of field: %s", strings.Join(fieldPath, "."))
  83. case 1:
  84. default:
  85. grpclog.Printf("too many field values: %s", strings.Join(fieldPath, "."))
  86. }
  87. return populateField(m, values[0], props)
  88. }
  89. // fieldByProtoName looks up a field whose corresponding protobuf field name is "name".
  90. // "m" must be a struct value. It returns zero reflect.Value if no such field found.
  91. func fieldByProtoName(m reflect.Value, name string) (reflect.Value, *proto.Properties, error) {
  92. props := proto.GetProperties(m.Type())
  93. // look up field name in oneof map
  94. if op, ok := props.OneofTypes[name]; ok {
  95. v := reflect.New(op.Type.Elem())
  96. field := m.Field(op.Field)
  97. if !field.IsNil() {
  98. return reflect.Value{}, nil, fmt.Errorf("field already set for %s oneof", props.Prop[op.Field].OrigName)
  99. }
  100. field.Set(v)
  101. return v.Elem().Field(0), op.Prop, nil
  102. }
  103. for _, p := range props.Prop {
  104. if p.OrigName == name {
  105. return m.FieldByName(p.Name), p, nil
  106. }
  107. if p.JSONName == name {
  108. return m.FieldByName(p.Name), p, nil
  109. }
  110. }
  111. return reflect.Value{}, nil, nil
  112. }
  113. func populateRepeatedField(f reflect.Value, values []string, props *proto.Properties) error {
  114. elemType := f.Type().Elem()
  115. // is the destination field a slice of an enumeration type?
  116. if enumValMap := proto.EnumValueMap(props.Enum); enumValMap != nil {
  117. return populateFieldEnumRepeated(f, values, enumValMap)
  118. }
  119. conv, ok := convFromType[elemType.Kind()]
  120. if !ok {
  121. return fmt.Errorf("unsupported field type %s", elemType)
  122. }
  123. f.Set(reflect.MakeSlice(f.Type(), len(values), len(values)).Convert(f.Type()))
  124. for i, v := range values {
  125. result := conv.Call([]reflect.Value{reflect.ValueOf(v)})
  126. if err := result[1].Interface(); err != nil {
  127. return err.(error)
  128. }
  129. f.Index(i).Set(result[0].Convert(f.Index(i).Type()))
  130. }
  131. return nil
  132. }
  133. func populateField(f reflect.Value, value string, props *proto.Properties) error {
  134. // Handle well known type
  135. type wkt interface {
  136. XXX_WellKnownType() string
  137. }
  138. if wkt, ok := f.Addr().Interface().(wkt); ok {
  139. switch wkt.XXX_WellKnownType() {
  140. case "Timestamp":
  141. if value == "null" {
  142. f.Field(0).SetInt(0)
  143. f.Field(1).SetInt(0)
  144. return nil
  145. }
  146. t, err := time.Parse(time.RFC3339Nano, value)
  147. if err != nil {
  148. return fmt.Errorf("bad Timestamp: %v", err)
  149. }
  150. f.Field(0).SetInt(int64(t.Unix()))
  151. f.Field(1).SetInt(int64(t.Nanosecond()))
  152. return nil
  153. case "DoubleValue":
  154. fallthrough
  155. case "FloatValue":
  156. float64Val, err := strconv.ParseFloat(value, 64)
  157. if err != nil {
  158. return fmt.Errorf("bad DoubleValue: %s", value)
  159. }
  160. f.Field(0).SetFloat(float64Val)
  161. return nil
  162. case "Int64Value":
  163. fallthrough
  164. case "Int32Value":
  165. int64Val, err := strconv.ParseInt(value, 10, 64)
  166. if err != nil {
  167. return fmt.Errorf("bad DoubleValue: %s", value)
  168. }
  169. f.Field(0).SetInt(int64Val)
  170. return nil
  171. case "UInt64Value":
  172. fallthrough
  173. case "UInt32Value":
  174. uint64Val, err := strconv.ParseUint(value, 10, 64)
  175. if err != nil {
  176. return fmt.Errorf("bad DoubleValue: %s", value)
  177. }
  178. f.Field(0).SetUint(uint64Val)
  179. return nil
  180. case "BoolValue":
  181. if value == "true" {
  182. f.Field(0).SetBool(true)
  183. } else if value == "false" {
  184. f.Field(0).SetBool(false)
  185. } else {
  186. return fmt.Errorf("bad BoolValue: %s", value)
  187. }
  188. return nil
  189. case "StringValue":
  190. f.Field(0).SetString(value)
  191. return nil
  192. }
  193. }
  194. // is the destination field an enumeration type?
  195. if enumValMap := proto.EnumValueMap(props.Enum); enumValMap != nil {
  196. return populateFieldEnum(f, value, enumValMap)
  197. }
  198. conv, ok := convFromType[f.Kind()]
  199. if !ok {
  200. return fmt.Errorf("unsupported field type %T", f)
  201. }
  202. result := conv.Call([]reflect.Value{reflect.ValueOf(value)})
  203. if err := result[1].Interface(); err != nil {
  204. return err.(error)
  205. }
  206. f.Set(result[0].Convert(f.Type()))
  207. return nil
  208. }
  209. func convertEnum(value string, t reflect.Type, enumValMap map[string]int32) (reflect.Value, error) {
  210. // see if it's an enumeration string
  211. if enumVal, ok := enumValMap[value]; ok {
  212. return reflect.ValueOf(enumVal).Convert(t), nil
  213. }
  214. // check for an integer that matches an enumeration value
  215. eVal, err := strconv.Atoi(value)
  216. if err != nil {
  217. return reflect.Value{}, fmt.Errorf("%s is not a valid %s", value, t)
  218. }
  219. for _, v := range enumValMap {
  220. if v == int32(eVal) {
  221. return reflect.ValueOf(eVal).Convert(t), nil
  222. }
  223. }
  224. return reflect.Value{}, fmt.Errorf("%s is not a valid %s", value, t)
  225. }
  226. func populateFieldEnum(f reflect.Value, value string, enumValMap map[string]int32) error {
  227. cval, err := convertEnum(value, f.Type(), enumValMap)
  228. if err != nil {
  229. return err
  230. }
  231. f.Set(cval)
  232. return nil
  233. }
  234. func populateFieldEnumRepeated(f reflect.Value, values []string, enumValMap map[string]int32) error {
  235. elemType := f.Type().Elem()
  236. f.Set(reflect.MakeSlice(f.Type(), len(values), len(values)).Convert(f.Type()))
  237. for i, v := range values {
  238. result, err := convertEnum(v, elemType, enumValMap)
  239. if err != nil {
  240. return err
  241. }
  242. f.Index(i).Set(result)
  243. }
  244. return nil
  245. }
  246. var (
  247. convFromType = map[reflect.Kind]reflect.Value{
  248. reflect.String: reflect.ValueOf(String),
  249. reflect.Bool: reflect.ValueOf(Bool),
  250. reflect.Float64: reflect.ValueOf(Float64),
  251. reflect.Float32: reflect.ValueOf(Float32),
  252. reflect.Int64: reflect.ValueOf(Int64),
  253. reflect.Int32: reflect.ValueOf(Int32),
  254. reflect.Uint64: reflect.ValueOf(Uint64),
  255. reflect.Uint32: reflect.ValueOf(Uint32),
  256. // TODO(yugui) Support []byte
  257. }
  258. )