binding.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. package hero
  2. import (
  3. "fmt"
  4. "reflect"
  5. "sort"
  6. "github.com/kataras/iris/context"
  7. )
  8. // binding contains the Dependency and the Input, it's the result of a function or struct + dependencies.
  9. type binding struct {
  10. Dependency *Dependency
  11. Input *Input
  12. }
  13. // Input contains the input reference of which a dependency is binded to.
  14. type Input struct {
  15. Index int // for func inputs
  16. StructFieldIndex []int // for struct fields in order to support embedded ones.
  17. Type reflect.Type
  18. selfValue reflect.Value // reflect.ValueOf(*Input) cache.
  19. }
  20. func newInput(typ reflect.Type, index int, structFieldIndex []int) *Input {
  21. in := &Input{
  22. Index: index,
  23. StructFieldIndex: structFieldIndex,
  24. Type: typ,
  25. }
  26. in.selfValue = reflect.ValueOf(in)
  27. return in
  28. }
  29. // String returns the string representation of a binding.
  30. func (b *binding) String() string {
  31. index := fmt.Sprintf("%d", b.Input.Index)
  32. if len(b.Input.StructFieldIndex) > 0 {
  33. for j, i := range b.Input.StructFieldIndex {
  34. if j == 0 {
  35. index = fmt.Sprintf("%d", i)
  36. continue
  37. }
  38. index += fmt.Sprintf(".%d", i)
  39. }
  40. }
  41. return fmt.Sprintf("[%s:%s] maps to [%s]", index, b.Input.Type.String(), b.Dependency)
  42. }
  43. // Equal compares "b" and "other" bindings and reports whether they are referring to the same values.
  44. func (b *binding) Equal(other *binding) bool {
  45. if b == nil {
  46. return other == nil
  47. }
  48. if other == nil {
  49. return false
  50. }
  51. // if b.String() != other.String() {
  52. // return false
  53. // }
  54. if expected, got := b.Dependency != nil, other.Dependency != nil; expected != got {
  55. return false
  56. }
  57. if expected, got := fmt.Sprintf("%v", b.Dependency.OriginalValue), fmt.Sprintf("%v", other.Dependency.OriginalValue); expected != got {
  58. return false
  59. }
  60. if expected, got := b.Dependency.DestType != nil, other.Dependency.DestType != nil; expected != got {
  61. return false
  62. }
  63. if b.Dependency.DestType != nil {
  64. if expected, got := b.Dependency.DestType.String(), other.Dependency.DestType.String(); expected != got {
  65. return false
  66. }
  67. }
  68. if expected, got := b.Input != nil, other.Input != nil; expected != got {
  69. return false
  70. }
  71. if b.Input != nil {
  72. if expected, got := b.Input.Index, other.Input.Index; expected != got {
  73. return false
  74. }
  75. if expected, got := b.Input.Type.String(), other.Input.Type.String(); expected != got {
  76. return false
  77. }
  78. if expected, got := b.Input.StructFieldIndex, other.Input.StructFieldIndex; !reflect.DeepEqual(expected, got) {
  79. return false
  80. }
  81. }
  82. return true
  83. }
  84. func matchDependency(dep *Dependency, in reflect.Type) bool {
  85. if dep.Explicit {
  86. return dep.DestType == in
  87. }
  88. return dep.DestType == nil || equalTypes(dep.DestType, in)
  89. }
  90. func getBindingsFor(inputs []reflect.Type, deps []*Dependency, paramsCount int) (bindings []*binding) {
  91. // Path parameter start index is the result of [total path parameters] - [total func path parameters inputs],
  92. // moving from last to first path parameters and first to last (probably) available input args.
  93. //
  94. // That way the above will work as expected:
  95. // 1. mvc.New(app.Party("/path/{firstparam}")).Handle(....Controller.GetBy(secondparam string))
  96. // 2. mvc.New(app.Party("/path/{firstparam}/{secondparam}")).Handle(...Controller.GetBy(firstparam, secondparam string))
  97. // 3. usersRouter := app.Party("/users/{id:uint64}"); usersRouter.ConfigureContainer().Handle(method, "/", handler(id uint64))
  98. // 4. usersRouter.Party("/friends").ConfigureContainer().Handle(method, "/{friendID:uint64}", handler(friendID uint64))
  99. //
  100. // Therefore, count the inputs that can be path parameters first.
  101. shouldBindParams := make(map[int]struct{})
  102. totalParamsExpected := 0
  103. if paramsCount != -1 {
  104. for i, in := range inputs {
  105. if _, canBePathParameter := context.ParamResolvers[in]; !canBePathParameter {
  106. continue
  107. }
  108. shouldBindParams[i] = struct{}{}
  109. totalParamsExpected++
  110. }
  111. }
  112. startParamIndex := paramsCount - totalParamsExpected
  113. if startParamIndex < 0 {
  114. startParamIndex = 0
  115. }
  116. lastParamIndex := startParamIndex
  117. getParamIndex := func() int {
  118. paramIndex := lastParamIndex
  119. lastParamIndex++
  120. return paramIndex
  121. }
  122. bindedInput := make(map[int]struct{})
  123. for i, in := range inputs { //order matters.
  124. _, canBePathParameter := shouldBindParams[i]
  125. prevN := len(bindings) // to check if a new binding is attached; a dependency was matched (see below).
  126. for j := len(deps) - 1; j >= 0; j-- {
  127. d := deps[j]
  128. // Note: we could use the same slice to return.
  129. //
  130. // Add all dynamic dependencies (caller-selecting) and the exact typed dependencies.
  131. //
  132. // A dependency can only be matched to 1 value, and 1 value has a single dependency
  133. // (e.g. to avoid conflicting path parameters of the same type).
  134. if _, alreadyBinded := bindedInput[j]; alreadyBinded {
  135. continue
  136. }
  137. match := matchDependency(d, in)
  138. if !match {
  139. continue
  140. }
  141. if canBePathParameter {
  142. // wrap the existing dependency handler.
  143. paramHandler := paramDependencyHandler(getParamIndex())
  144. prevHandler := d.Handle
  145. d.Handle = func(ctx *context.Context, input *Input) (reflect.Value, error) {
  146. v, err := paramHandler(ctx, input)
  147. if err != nil {
  148. v, err = prevHandler(ctx, input)
  149. }
  150. return v, err
  151. }
  152. d.Static = false
  153. d.OriginalValue = nil
  154. }
  155. bindings = append(bindings, &binding{
  156. Dependency: d,
  157. Input: newInput(in, i, nil),
  158. })
  159. if !d.Explicit { // if explicit then it can be binded to more than one input
  160. bindedInput[j] = struct{}{}
  161. }
  162. break
  163. }
  164. if prevN == len(bindings) {
  165. if canBePathParameter {
  166. // no new dependency added for this input,
  167. // let's check for path parameters.
  168. bindings = append(bindings, paramBinding(i, getParamIndex(), in))
  169. continue
  170. }
  171. // else add builtin bindings that may be registered by user too, but they didn't.
  172. if isPayloadType(in) {
  173. bindings = append(bindings, payloadBinding(i, in))
  174. continue
  175. }
  176. }
  177. }
  178. return
  179. }
  180. func isPayloadType(in reflect.Type) bool {
  181. switch indirectType(in).Kind() {
  182. case reflect.Struct, reflect.Slice, reflect.Ptr:
  183. return true
  184. default:
  185. return false
  186. }
  187. }
  188. func getBindingsForFunc(fn reflect.Value, dependencies []*Dependency, paramsCount int) []*binding {
  189. fnTyp := fn.Type()
  190. if !isFunc(fnTyp) {
  191. panic("bindings: unresolved: not a func type")
  192. }
  193. n := fnTyp.NumIn()
  194. inputs := make([]reflect.Type, n)
  195. for i := 0; i < n; i++ {
  196. inputs[i] = fnTyp.In(i)
  197. }
  198. bindings := getBindingsFor(inputs, dependencies, paramsCount)
  199. if expected, got := n, len(bindings); expected > got {
  200. panic(fmt.Sprintf("expected [%d] bindings (input parameters) but got [%d]", expected, got))
  201. }
  202. return bindings
  203. }
  204. func getBindingsForStruct(v reflect.Value, dependencies []*Dependency, paramsCount int, sorter Sorter) (bindings []*binding) {
  205. typ := indirectType(v.Type())
  206. if typ.Kind() != reflect.Struct {
  207. panic("bindings: unresolved: no struct type")
  208. }
  209. // get bindings from any struct's non zero values first, including unexported.
  210. elem := reflect.Indirect(v)
  211. nonZero := lookupNonZeroFieldValues(elem)
  212. for _, f := range nonZero {
  213. // fmt.Printf("Controller [%s] | NonZero | Field Index: %v | Field Type: %s\n", typ, f.Index, f.Type)
  214. bindings = append(bindings, &binding{
  215. Dependency: NewDependency(elem.FieldByIndex(f.Index).Interface()),
  216. Input: newInput(f.Type, f.Index[0], f.Index),
  217. })
  218. }
  219. fields, stateless := lookupFields(elem, true, true, nil)
  220. n := len(fields)
  221. if n > 1 && sorter != nil {
  222. sort.Slice(fields, func(i, j int) bool {
  223. return sorter(fields[i].Type, fields[j].Type)
  224. })
  225. }
  226. inputs := make([]reflect.Type, n)
  227. for i := 0; i < n; i++ {
  228. // fmt.Printf("Controller [%s] | Field Index: %v | Field Type: %s\n", typ, fields[i].Index, fields[i].Type)
  229. inputs[i] = fields[i].Type
  230. }
  231. exportedBindings := getBindingsFor(inputs, dependencies, paramsCount)
  232. // fmt.Printf("Controller [%s] | Inputs length: %d vs Bindings length: %d | NonZero: %d | Stateless : %d\n",
  233. // typ, n, len(exportedBindings), len(nonZero), stateless)
  234. // for i, b := range exportedBindings {
  235. // fmt.Printf("[%d] [Static=%v] %#+v\n", i, b.Dependency.Static, b.Dependency.OriginalValue)
  236. // }
  237. if stateless == 0 && len(nonZero) >= len(exportedBindings) {
  238. // if we have not a single stateless and fields are defined then just return.
  239. // Note(@kataras): this can accept further improvements.
  240. return
  241. }
  242. // get declared bindings from deps.
  243. bindings = append(bindings, exportedBindings...)
  244. for _, binding := range bindings {
  245. // fmt.Printf(""Controller [%s] | Binding: %s\n", typ, binding.String())
  246. if len(binding.Input.StructFieldIndex) == 0 {
  247. // set correctly the input's field index.
  248. structFieldIndex := fields[binding.Input.Index].Index
  249. binding.Input.StructFieldIndex = structFieldIndex
  250. }
  251. // fmt.Printf("Controller [%s] | binding Index: %v | binding Type: %s\n", typ, binding.Input.StructFieldIndex, binding.Input.Type)
  252. // fmt.Printf("Controller [%s] Set [%s] to struct field index: %v\n", typ.String(), binding.Input.Type.String(), binding.Input.StructFieldIndex)
  253. }
  254. return
  255. }
  256. /*
  257. Builtin dynamic bindings.
  258. */
  259. func paramBinding(index, paramIndex int, typ reflect.Type) *binding {
  260. return &binding{
  261. Dependency: &Dependency{Handle: paramDependencyHandler(paramIndex), DestType: typ, Source: getSource()},
  262. Input: newInput(typ, index, nil),
  263. }
  264. }
  265. func paramDependencyHandler(paramIndex int) DependencyHandler {
  266. return func(ctx *context.Context, input *Input) (reflect.Value, error) {
  267. if ctx.Params().Len() <= paramIndex {
  268. return emptyValue, ErrSeeOther
  269. }
  270. return reflect.ValueOf(ctx.Params().Store[paramIndex].ValueRaw), nil
  271. }
  272. }
  273. // registered if input parameters are more than matched dependencies.
  274. // It binds an input to a request body based on the request content-type header
  275. // (JSON, Protobuf, Msgpack, XML, YAML, Query, Form).
  276. func payloadBinding(index int, typ reflect.Type) *binding {
  277. // fmt.Printf("Register payload binding for index: %d and type: %s\n", index, typ.String())
  278. return &binding{
  279. Dependency: &Dependency{
  280. Handle: func(ctx *context.Context, input *Input) (newValue reflect.Value, err error) {
  281. wasPtr := input.Type.Kind() == reflect.Ptr
  282. if serveDepsV := ctx.Values().Get(context.DependenciesContextKey); serveDepsV != nil {
  283. if serveDeps, ok := serveDepsV.(context.DependenciesMap); ok {
  284. if newValue, ok = serveDeps[typ]; ok {
  285. return
  286. }
  287. }
  288. }
  289. if input.Type.Kind() == reflect.Slice {
  290. newValue = reflect.New(reflect.SliceOf(indirectType(input.Type)))
  291. } else {
  292. newValue = reflect.New(indirectType(input.Type))
  293. }
  294. ptr := newValue.Interface()
  295. err = ctx.ReadBody(ptr)
  296. if !wasPtr {
  297. newValue = newValue.Elem()
  298. }
  299. return
  300. },
  301. Source: getSource(),
  302. },
  303. Input: newInput(typ, index, nil),
  304. }
  305. }