mirror of
https://github.com/kataras/iris.git
synced 2025-01-23 10:41:03 +01:00
👔 next version: some linting
Former-commit-id: a102fbb90e2a8a8b09fcb9c9e0c370e4078b74d1
This commit is contained in:
parent
2756435446
commit
1c9b592088
|
@ -8,11 +8,13 @@ import (
|
||||||
"github.com/kataras/iris/v12/context"
|
"github.com/kataras/iris/v12/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Binding struct {
|
// binding contains the Dependency and the Input, it's the result of a function or struct + dependencies.
|
||||||
|
type binding struct {
|
||||||
Dependency *Dependency
|
Dependency *Dependency
|
||||||
Input *Input
|
Input *Input
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Input contains the input reference of which a dependency is binded to.
|
||||||
type Input struct {
|
type Input struct {
|
||||||
Index int // for func inputs
|
Index int // for func inputs
|
||||||
StructFieldIndex []int // for struct fields in order to support embedded ones.
|
StructFieldIndex []int // for struct fields in order to support embedded ones.
|
||||||
|
@ -32,7 +34,8 @@ func newInput(typ reflect.Type, index int, structFieldIndex []int) *Input {
|
||||||
return in
|
return in
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Binding) String() string {
|
// String returns the string representation of a binding.
|
||||||
|
func (b *binding) String() string {
|
||||||
index := fmt.Sprintf("%d", b.Input.Index)
|
index := fmt.Sprintf("%d", b.Input.Index)
|
||||||
if len(b.Input.StructFieldIndex) > 0 {
|
if len(b.Input.StructFieldIndex) > 0 {
|
||||||
for j, i := range b.Input.StructFieldIndex {
|
for j, i := range b.Input.StructFieldIndex {
|
||||||
|
@ -47,7 +50,8 @@ func (b *Binding) String() string {
|
||||||
return fmt.Sprintf("[%s:%s] maps to [%s]", index, b.Input.Type.String(), b.Dependency)
|
return fmt.Sprintf("[%s:%s] maps to [%s]", index, b.Input.Type.String(), b.Dependency)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Binding) Equal(other *Binding) bool {
|
// Equal compares "b" and "other" bindings and reports whether they are referring to the same values.
|
||||||
|
func (b *binding) Equal(other *binding) bool {
|
||||||
if b == nil {
|
if b == nil {
|
||||||
return other == nil
|
return other == nil
|
||||||
}
|
}
|
||||||
|
@ -107,7 +111,7 @@ func matchDependency(dep *Dependency, in reflect.Type) bool {
|
||||||
return dep.DestType == nil || equalTypes(dep.DestType, in)
|
return dep.DestType == nil || equalTypes(dep.DestType, in)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getBindingsFor(inputs []reflect.Type, deps []*Dependency, paramStartIndex int) (bindings []*Binding) {
|
func getBindingsFor(inputs []reflect.Type, deps []*Dependency, paramStartIndex int) (bindings []*binding) {
|
||||||
bindedInput := make(map[int]struct{})
|
bindedInput := make(map[int]struct{})
|
||||||
|
|
||||||
// lastParamIndex is used to bind parameters correctly when:
|
// lastParamIndex is used to bind parameters correctly when:
|
||||||
|
@ -170,7 +174,7 @@ func getBindingsFor(inputs []reflect.Type, deps []*Dependency, paramStartIndex i
|
||||||
d.OriginalValue = nil
|
d.OriginalValue = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
bindings = append(bindings, &Binding{
|
bindings = append(bindings, &binding{
|
||||||
Dependency: d,
|
Dependency: d,
|
||||||
Input: newInput(in, i, nil),
|
Input: newInput(in, i, nil),
|
||||||
})
|
})
|
||||||
|
@ -201,7 +205,7 @@ func getBindingsFor(inputs []reflect.Type, deps []*Dependency, paramStartIndex i
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func getBindingsForFunc(fn reflect.Value, dependencies []*Dependency, paramStartIndex int) []*Binding {
|
func getBindingsForFunc(fn reflect.Value, dependencies []*Dependency, paramStartIndex int) []*binding {
|
||||||
fnTyp := fn.Type()
|
fnTyp := fn.Type()
|
||||||
if !isFunc(fnTyp) {
|
if !isFunc(fnTyp) {
|
||||||
panic("bindings: unresolved: not a func type")
|
panic("bindings: unresolved: not a func type")
|
||||||
|
@ -221,7 +225,7 @@ func getBindingsForFunc(fn reflect.Value, dependencies []*Dependency, paramStart
|
||||||
return bindings
|
return bindings
|
||||||
}
|
}
|
||||||
|
|
||||||
func getBindingsForStruct(v reflect.Value, dependencies []*Dependency, paramStartIndex int, sorter Sorter) (bindings []*Binding) {
|
func getBindingsForStruct(v reflect.Value, dependencies []*Dependency, paramStartIndex int, sorter Sorter) (bindings []*binding) {
|
||||||
typ := indirectType(v.Type())
|
typ := indirectType(v.Type())
|
||||||
if typ.Kind() != reflect.Struct {
|
if typ.Kind() != reflect.Struct {
|
||||||
panic("bindings: unresolved: no struct type")
|
panic("bindings: unresolved: no struct type")
|
||||||
|
@ -232,7 +236,7 @@ func getBindingsForStruct(v reflect.Value, dependencies []*Dependency, paramStar
|
||||||
nonZero := lookupNonZeroFieldValues(elem)
|
nonZero := lookupNonZeroFieldValues(elem)
|
||||||
for _, f := range nonZero {
|
for _, f := range nonZero {
|
||||||
// fmt.Printf("Controller [%s] | NonZero | Field Index: %v | Field Type: %s\n", typ, f.Index, f.Type)
|
// fmt.Printf("Controller [%s] | NonZero | Field Index: %v | Field Type: %s\n", typ, f.Index, f.Type)
|
||||||
bindings = append(bindings, &Binding{
|
bindings = append(bindings, &binding{
|
||||||
Dependency: NewDependency(elem.FieldByIndex(f.Index).Interface()),
|
Dependency: NewDependency(elem.FieldByIndex(f.Index).Interface()),
|
||||||
Input: newInput(f.Type, f.Index[0], f.Index),
|
Input: newInput(f.Type, f.Index[0], f.Index),
|
||||||
})
|
})
|
||||||
|
@ -268,7 +272,7 @@ func getBindingsForStruct(v reflect.Value, dependencies []*Dependency, paramStar
|
||||||
binding.Input.StructFieldIndex = structFieldIndex
|
binding.Input.StructFieldIndex = structFieldIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
// fmt.Printf("Controller [%s] | Binding Index: %v | Binding Type: %s\n", typ, binding.Input.StructFieldIndex, binding.Input.Type)
|
// fmt.Printf("Controller [%s] | binding Index: %v | binding Type: %s\n", typ, binding.Input.StructFieldIndex, binding.Input.Type)
|
||||||
|
|
||||||
// fmt.Printf("Controller [%s] Set [%s] to struct field index: %v\n", typ.String(), binding.Input.Type.String(), structFieldIndex)
|
// fmt.Printf("Controller [%s] Set [%s] to struct field index: %v\n", typ.String(), binding.Input.Type.String(), structFieldIndex)
|
||||||
}
|
}
|
||||||
|
@ -280,8 +284,8 @@ func getBindingsForStruct(v reflect.Value, dependencies []*Dependency, paramStar
|
||||||
Builtin dynamic bindings.
|
Builtin dynamic bindings.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
func paramBinding(index, paramIndex int, typ reflect.Type) *Binding {
|
func paramBinding(index, paramIndex int, typ reflect.Type) *binding {
|
||||||
return &Binding{
|
return &binding{
|
||||||
Dependency: &Dependency{Handle: paramDependencyHandler(paramIndex), DestType: typ, Source: getSource()},
|
Dependency: &Dependency{Handle: paramDependencyHandler(paramIndex), DestType: typ, Source: getSource()},
|
||||||
Input: newInput(typ, index, nil),
|
Input: newInput(typ, index, nil),
|
||||||
}
|
}
|
||||||
|
@ -299,8 +303,8 @@ func paramDependencyHandler(paramIndex int) DependencyHandler {
|
||||||
|
|
||||||
// registered if input parameters are more than matched dependencies.
|
// registered if input parameters are more than matched dependencies.
|
||||||
// It binds an input to a request body based on the request content-type header (JSON, XML, YAML, Query, Form).
|
// It binds an input to a request body based on the request content-type header (JSON, XML, YAML, Query, Form).
|
||||||
func payloadBinding(index int, typ reflect.Type) *Binding {
|
func payloadBinding(index int, typ reflect.Type) *binding {
|
||||||
return &Binding{
|
return &binding{
|
||||||
Dependency: &Dependency{
|
Dependency: &Dependency{
|
||||||
Handle: func(ctx context.Context, input *Input) (newValue reflect.Value, err error) {
|
Handle: func(ctx context.Context, input *Input) (newValue reflect.Value, err error) {
|
||||||
wasPtr := input.Type.Kind() == reflect.Ptr
|
wasPtr := input.Type.Kind() == reflect.Ptr
|
||||||
|
|
|
@ -11,8 +11,14 @@ import (
|
||||||
"github.com/kataras/iris/v12/sessions"
|
"github.com/kataras/iris/v12/sessions"
|
||||||
)
|
)
|
||||||
|
|
||||||
func contextBinding(index int) *Binding {
|
var (
|
||||||
return &Binding{
|
stdContextTyp = reflect.TypeOf((*stdContext.Context)(nil)).Elem()
|
||||||
|
sessionTyp = reflect.TypeOf((*sessions.Session)(nil))
|
||||||
|
timeTyp = reflect.TypeOf((*time.Time)(nil)).Elem()
|
||||||
|
)
|
||||||
|
|
||||||
|
func contextBinding(index int) *binding {
|
||||||
|
return &binding{
|
||||||
Dependency: BuiltinDependencies[0],
|
Dependency: BuiltinDependencies[0],
|
||||||
Input: &Input{Type: BuiltinDependencies[0].DestType, Index: index},
|
Input: &Input{Type: BuiltinDependencies[0].DestType, Index: index},
|
||||||
}
|
}
|
||||||
|
@ -64,55 +70,55 @@ func TestGetBindingsForFunc(t *testing.T) {
|
||||||
|
|
||||||
var tests = []struct {
|
var tests = []struct {
|
||||||
Func interface{}
|
Func interface{}
|
||||||
Expected []*Binding
|
Expected []*binding
|
||||||
}{
|
}{
|
||||||
{ // 0
|
{ // 0
|
||||||
Func: func(ctx context.Context) {
|
Func: func(ctx context.Context) {
|
||||||
ctx.WriteString("t1")
|
ctx.WriteString("t1")
|
||||||
},
|
},
|
||||||
Expected: []*Binding{contextBinding(0)},
|
Expected: []*binding{contextBinding(0)},
|
||||||
},
|
},
|
||||||
{ // 1
|
{ // 1
|
||||||
Func: func(ctx context.Context) error {
|
Func: func(ctx context.Context) error {
|
||||||
return fmt.Errorf("err1")
|
return fmt.Errorf("err1")
|
||||||
},
|
},
|
||||||
Expected: []*Binding{contextBinding(0)},
|
Expected: []*binding{contextBinding(0)},
|
||||||
},
|
},
|
||||||
{ // 2
|
{ // 2
|
||||||
Func: func(ctx context.Context) testResponse {
|
Func: func(ctx context.Context) testResponse {
|
||||||
return testResponse{Name: "name"}
|
return testResponse{Name: "name"}
|
||||||
},
|
},
|
||||||
Expected: []*Binding{contextBinding(0)},
|
Expected: []*binding{contextBinding(0)},
|
||||||
},
|
},
|
||||||
{ // 3
|
{ // 3
|
||||||
Func: func(in testRequest) (testResponse, error) {
|
Func: func(in testRequest) (testResponse, error) {
|
||||||
return testResponse{Name: "email of " + in.Email}, nil
|
return testResponse{Name: "email of " + in.Email}, nil
|
||||||
},
|
},
|
||||||
Expected: []*Binding{{Dependency: deps[2], Input: &Input{Index: 0, Type: testRequestTyp}}},
|
Expected: []*binding{{Dependency: deps[2], Input: &Input{Index: 0, Type: testRequestTyp}}},
|
||||||
},
|
},
|
||||||
{ // 4
|
{ // 4
|
||||||
Func: func(in testRequest) (testResponse, error) {
|
Func: func(in testRequest) (testResponse, error) {
|
||||||
return testResponse{Name: "not valid "}, fmt.Errorf("invalid")
|
return testResponse{Name: "not valid "}, fmt.Errorf("invalid")
|
||||||
},
|
},
|
||||||
Expected: []*Binding{{Dependency: deps[2], Input: &Input{Index: 0, Type: testRequestTyp}}},
|
Expected: []*binding{{Dependency: deps[2], Input: &Input{Index: 0, Type: testRequestTyp}}},
|
||||||
},
|
},
|
||||||
{ // 5
|
{ // 5
|
||||||
Func: func(ctx context.Context, in testRequest) testResponse {
|
Func: func(ctx context.Context, in testRequest) testResponse {
|
||||||
return testResponse{Name: "(with ctx) email of " + in.Email}
|
return testResponse{Name: "(with ctx) email of " + in.Email}
|
||||||
},
|
},
|
||||||
Expected: []*Binding{contextBinding(0), {Dependency: deps[2], Input: &Input{Index: 1, Type: testRequestTyp}}},
|
Expected: []*binding{contextBinding(0), {Dependency: deps[2], Input: &Input{Index: 1, Type: testRequestTyp}}},
|
||||||
},
|
},
|
||||||
{ // 6
|
{ // 6
|
||||||
Func: func(in testRequest, ctx context.Context) testResponse { // reversed.
|
Func: func(in testRequest, ctx context.Context) testResponse { // reversed.
|
||||||
return testResponse{Name: "(with ctx) email of " + in.Email}
|
return testResponse{Name: "(with ctx) email of " + in.Email}
|
||||||
},
|
},
|
||||||
Expected: []*Binding{{Dependency: deps[2], Input: &Input{Index: 0, Type: testRequestTyp}}, contextBinding(1)},
|
Expected: []*binding{{Dependency: deps[2], Input: &Input{Index: 0, Type: testRequestTyp}}, contextBinding(1)},
|
||||||
},
|
},
|
||||||
{ // 7
|
{ // 7
|
||||||
Func: func(in testRequest, ctx context.Context, in2 string) testResponse { // reversed.
|
Func: func(in testRequest, ctx context.Context, in2 string) testResponse { // reversed.
|
||||||
return testResponse{Name: "(with ctx) email of " + in.Email + "and in2: " + in2}
|
return testResponse{Name: "(with ctx) email of " + in.Email + "and in2: " + in2}
|
||||||
},
|
},
|
||||||
Expected: []*Binding{
|
Expected: []*binding{
|
||||||
{
|
{
|
||||||
Dependency: deps[2],
|
Dependency: deps[2],
|
||||||
Input: &Input{Index: 0, Type: testRequestTyp},
|
Input: &Input{Index: 0, Type: testRequestTyp},
|
||||||
|
@ -128,7 +134,7 @@ func TestGetBindingsForFunc(t *testing.T) {
|
||||||
Func: func(in testRequest, ctx context.Context, in2, in3 string) testResponse { // reversed.
|
Func: func(in testRequest, ctx context.Context, in2, in3 string) testResponse { // reversed.
|
||||||
return testResponse{Name: "(with ctx) email of " + in.Email + " | in2: " + in2 + " in3: " + in3}
|
return testResponse{Name: "(with ctx) email of " + in.Email + " | in2: " + in2 + " in3: " + in3}
|
||||||
},
|
},
|
||||||
Expected: []*Binding{
|
Expected: []*binding{
|
||||||
{
|
{
|
||||||
Dependency: deps[2],
|
Dependency: deps[2],
|
||||||
Input: &Input{Index: 0, Type: testRequestTyp},
|
Input: &Input{Index: 0, Type: testRequestTyp},
|
||||||
|
@ -148,7 +154,7 @@ func TestGetBindingsForFunc(t *testing.T) {
|
||||||
Func: func(ctx context.Context, in testRequest, in2 testRequest2) testResponse {
|
Func: func(ctx context.Context, in testRequest, in2 testRequest2) testResponse {
|
||||||
return testResponse{Name: fmt.Sprintf("(with ctx) email of %s and in2.Age %d", in.Email, in2.Age)}
|
return testResponse{Name: fmt.Sprintf("(with ctx) email of %s and in2.Age %d", in.Email, in2.Age)}
|
||||||
},
|
},
|
||||||
Expected: []*Binding{
|
Expected: []*binding{
|
||||||
contextBinding(0),
|
contextBinding(0),
|
||||||
{
|
{
|
||||||
Dependency: deps[2],
|
Dependency: deps[2],
|
||||||
|
@ -170,7 +176,7 @@ func TestGetBindingsForFunc(t *testing.T) {
|
||||||
Func: func(userID string, age int) testResponse {
|
Func: func(userID string, age int) testResponse {
|
||||||
return testResponse{Name: "in from path parameters"}
|
return testResponse{Name: "in from path parameters"}
|
||||||
},
|
},
|
||||||
Expected: []*Binding{
|
Expected: []*binding{
|
||||||
paramBinding(0, 0, reflect.TypeOf("")),
|
paramBinding(0, 0, reflect.TypeOf("")),
|
||||||
paramBinding(1, 1, reflect.TypeOf(0)),
|
paramBinding(1, 1, reflect.TypeOf(0)),
|
||||||
},
|
},
|
||||||
|
@ -180,7 +186,7 @@ func TestGetBindingsForFunc(t *testing.T) {
|
||||||
Func: func(ctx stdContext.Context, s *sessions.Session, t time.Time) testResponse {
|
Func: func(ctx stdContext.Context, s *sessions.Session, t time.Time) testResponse {
|
||||||
return testResponse{"from std context and session"}
|
return testResponse{"from std context and session"}
|
||||||
},
|
},
|
||||||
Expected: []*Binding{
|
Expected: []*binding{
|
||||||
{
|
{
|
||||||
Dependency: NewDependency(BuiltinDependencies[1]),
|
Dependency: NewDependency(BuiltinDependencies[1]),
|
||||||
Input: &Input{Index: 0, Type: stdContextTyp},
|
Input: &Input{Index: 0, Type: stdContextTyp},
|
||||||
|
@ -191,7 +197,7 @@ func TestGetBindingsForFunc(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Dependency: NewDependency(BuiltinDependencies[3]),
|
Dependency: NewDependency(BuiltinDependencies[3]),
|
||||||
Input: &Input{Index: 2, Type: reflect.TypeOf(time.Time{})},
|
Input: &Input{Index: 2, Type: timeTyp},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -307,7 +313,7 @@ func TestBindingsForStruct(t *testing.T) {
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
|
|
||||||
var autoBindings = []*Binding{
|
var autoBindings = []*binding{
|
||||||
payloadBinding(0, reflect.TypeOf(embedded1{})),
|
payloadBinding(0, reflect.TypeOf(embedded1{})),
|
||||||
payloadBinding(1, reflect.TypeOf(embedded2{})),
|
payloadBinding(1, reflect.TypeOf(embedded2{})),
|
||||||
}
|
}
|
||||||
|
@ -319,12 +325,12 @@ func TestBindingsForStruct(t *testing.T) {
|
||||||
var tests = []struct {
|
var tests = []struct {
|
||||||
Value interface{}
|
Value interface{}
|
||||||
Registered []*Dependency
|
Registered []*Dependency
|
||||||
Expected []*Binding
|
Expected []*binding
|
||||||
}{
|
}{
|
||||||
{ // 0.
|
{ // 0.
|
||||||
Value: &controller{},
|
Value: &controller{},
|
||||||
Registered: deps,
|
Registered: deps,
|
||||||
Expected: []*Binding{
|
Expected: []*binding{
|
||||||
{
|
{
|
||||||
Dependency: deps[0],
|
Dependency: deps[0],
|
||||||
Input: &Input{Index: 0, StructFieldIndex: []int{0}, Type: reflect.TypeOf("")},
|
Input: &Input{Index: 0, StructFieldIndex: []int{0}, Type: reflect.TypeOf("")},
|
||||||
|
@ -338,7 +344,7 @@ func TestBindingsForStruct(t *testing.T) {
|
||||||
// 1. test controller with pre-defined variables.
|
// 1. test controller with pre-defined variables.
|
||||||
{
|
{
|
||||||
Value: &controller{Name: "name_struct", Service: new(serviceImpl)},
|
Value: &controller{Name: "name_struct", Service: new(serviceImpl)},
|
||||||
Expected: []*Binding{
|
Expected: []*binding{
|
||||||
{
|
{
|
||||||
Dependency: NewDependency("name_struct"),
|
Dependency: NewDependency("name_struct"),
|
||||||
Input: &Input{Index: 0, StructFieldIndex: []int{0}, Type: reflect.TypeOf("")},
|
Input: &Input{Index: 0, StructFieldIndex: []int{0}, Type: reflect.TypeOf("")},
|
||||||
|
@ -354,7 +360,7 @@ func TestBindingsForStruct(t *testing.T) {
|
||||||
{
|
{
|
||||||
Value: &controller{Name: "name_struct", Service: new(serviceImpl)},
|
Value: &controller{Name: "name_struct", Service: new(serviceImpl)},
|
||||||
Registered: deps,
|
Registered: deps,
|
||||||
Expected: []*Binding{
|
Expected: []*binding{
|
||||||
{
|
{
|
||||||
Dependency: NewDependency("name_struct"),
|
Dependency: NewDependency("name_struct"),
|
||||||
Input: &Input{Index: 0, StructFieldIndex: []int{0}, Type: reflect.TypeOf("")},
|
Input: &Input{Index: 0, StructFieldIndex: []int{0}, Type: reflect.TypeOf("")},
|
||||||
|
@ -369,7 +375,7 @@ func TestBindingsForStruct(t *testing.T) {
|
||||||
{
|
{
|
||||||
Value: &controllerEmbeddingExported{},
|
Value: &controllerEmbeddingExported{},
|
||||||
Registered: depsForAnonymousEmbedded,
|
Registered: depsForAnonymousEmbedded,
|
||||||
Expected: []*Binding{
|
Expected: []*binding{
|
||||||
{
|
{
|
||||||
Dependency: depsForAnonymousEmbedded[0],
|
Dependency: depsForAnonymousEmbedded[0],
|
||||||
Input: &Input{Index: 0, StructFieldIndex: []int{0, 0}, Type: reflect.TypeOf(0)},
|
Input: &Input{Index: 0, StructFieldIndex: []int{0, 0}, Type: reflect.TypeOf(0)},
|
||||||
|
@ -384,7 +390,7 @@ func TestBindingsForStruct(t *testing.T) {
|
||||||
{
|
{
|
||||||
Value: &controllerEmbeddingUnexported{},
|
Value: &controllerEmbeddingUnexported{},
|
||||||
Registered: depsForAnonymousEmbedded,
|
Registered: depsForAnonymousEmbedded,
|
||||||
Expected: []*Binding{
|
Expected: []*binding{
|
||||||
{
|
{
|
||||||
Dependency: depsForAnonymousEmbedded[0],
|
Dependency: depsForAnonymousEmbedded[0],
|
||||||
Input: &Input{Index: 0, StructFieldIndex: []int{0, 0}, Type: reflect.TypeOf(0)},
|
Input: &Input{Index: 0, StructFieldIndex: []int{0, 0}, Type: reflect.TypeOf(0)},
|
||||||
|
@ -411,7 +417,7 @@ func TestBindingsForStruct(t *testing.T) {
|
||||||
{
|
{
|
||||||
Value: &controller2{},
|
Value: &controller2{},
|
||||||
Registered: depsForFieldsOfStruct,
|
Registered: depsForFieldsOfStruct,
|
||||||
Expected: []*Binding{
|
Expected: []*binding{
|
||||||
{
|
{
|
||||||
Dependency: depsForFieldsOfStruct[0],
|
Dependency: depsForFieldsOfStruct[0],
|
||||||
Input: &Input{Index: 0, StructFieldIndex: []int{0}, Type: reflect.TypeOf(embedded1{})},
|
Input: &Input{Index: 0, StructFieldIndex: []int{0}, Type: reflect.TypeOf(embedded1{})},
|
||||||
|
@ -426,7 +432,7 @@ func TestBindingsForStruct(t *testing.T) {
|
||||||
{
|
{
|
||||||
Value: &controller3{},
|
Value: &controller3{},
|
||||||
Registered: []*Dependency{depsForFieldsOfStruct[0]},
|
Registered: []*Dependency{depsForFieldsOfStruct[0]},
|
||||||
Expected: []*Binding{
|
Expected: []*binding{
|
||||||
{
|
{
|
||||||
Dependency: depsForFieldsOfStruct[0],
|
Dependency: depsForFieldsOfStruct[0],
|
||||||
Input: &Input{Index: 0, StructFieldIndex: []int{0}, Type: reflect.TypeOf(embedded1{})},
|
Input: &Input{Index: 0, StructFieldIndex: []int{0}, Type: reflect.TypeOf(embedded1{})},
|
||||||
|
@ -437,7 +443,7 @@ func TestBindingsForStruct(t *testing.T) {
|
||||||
{
|
{
|
||||||
Value: &controller3{},
|
Value: &controller3{},
|
||||||
Registered: depsForFieldsOfStruct,
|
Registered: depsForFieldsOfStruct,
|
||||||
Expected: []*Binding{
|
Expected: []*binding{
|
||||||
{
|
{
|
||||||
Dependency: depsForFieldsOfStruct[0],
|
Dependency: depsForFieldsOfStruct[0],
|
||||||
Input: &Input{Index: 0, StructFieldIndex: []int{0}, Type: reflect.TypeOf(embedded1{})},
|
Input: &Input{Index: 0, StructFieldIndex: []int{0}, Type: reflect.TypeOf(embedded1{})},
|
||||||
|
@ -448,7 +454,7 @@ func TestBindingsForStruct(t *testing.T) {
|
||||||
{
|
{
|
||||||
Value: &controller{},
|
Value: &controller{},
|
||||||
Registered: depsInterfaces,
|
Registered: depsInterfaces,
|
||||||
Expected: []*Binding{
|
Expected: []*binding{
|
||||||
{
|
{
|
||||||
Dependency: depsInterfaces[0],
|
Dependency: depsInterfaces[0],
|
||||||
Input: &Input{Index: 0, StructFieldIndex: []int{0}, Type: reflect.TypeOf("")},
|
Input: &Input{Index: 0, StructFieldIndex: []int{0}, Type: reflect.TypeOf("")},
|
||||||
|
|
|
@ -2,17 +2,12 @@ package hero
|
||||||
|
|
||||||
import (
|
import (
|
||||||
stdContext "context"
|
stdContext "context"
|
||||||
"fmt"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/kataras/iris/v12/context"
|
"github.com/kataras/iris/v12/context"
|
||||||
"github.com/kataras/iris/v12/sessions"
|
"github.com/kataras/iris/v12/sessions"
|
||||||
)
|
)
|
||||||
|
|
||||||
func fatalf(format string, args ...interface{}) {
|
|
||||||
panic(fmt.Sprintf(format, args...))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Default is the default container value which can be used for dependencies share.
|
// Default is the default container value which can be used for dependencies share.
|
||||||
var Default = New()
|
var Default = New()
|
||||||
|
|
||||||
|
@ -40,13 +35,15 @@ type Container struct {
|
||||||
GetErrorHandler func(context.Context) ErrorHandler // cannot be nil.
|
GetErrorHandler func(context.Context) ErrorHandler // cannot be nil.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BuiltinDependencies is a list of builtin dependencies that are added on Container's initilization.
|
||||||
|
// Contains the iris context, standard context, iris sessions and time dependencies.
|
||||||
var BuiltinDependencies = []*Dependency{
|
var BuiltinDependencies = []*Dependency{
|
||||||
// iris context dependency.
|
// iris context dependency.
|
||||||
NewDependency(func(ctx context.Context) context.Context { return ctx }),
|
NewDependency(func(ctx context.Context) context.Context { return ctx }).Explicitly(),
|
||||||
// standard context dependency.
|
// standard context dependency.
|
||||||
NewDependency(func(ctx context.Context) stdContext.Context {
|
NewDependency(func(ctx context.Context) stdContext.Context {
|
||||||
return ctx.Request().Context()
|
return ctx.Request().Context()
|
||||||
}),
|
}).Explicitly(),
|
||||||
// iris session dependency.
|
// iris session dependency.
|
||||||
NewDependency(func(ctx context.Context) *sessions.Session {
|
NewDependency(func(ctx context.Context) *sessions.Session {
|
||||||
session := sessions.Get(ctx)
|
session := sessions.Get(ctx)
|
||||||
|
@ -55,11 +52,11 @@ var BuiltinDependencies = []*Dependency{
|
||||||
}
|
}
|
||||||
|
|
||||||
return session
|
return session
|
||||||
}),
|
}).Explicitly(),
|
||||||
// time.Time to time.Now dependency.
|
// time.Time to time.Now dependency.
|
||||||
NewDependency(func(ctx context.Context) time.Time {
|
NewDependency(func(ctx context.Context) time.Time {
|
||||||
return time.Now()
|
return time.Now()
|
||||||
}),
|
}).Explicitly(),
|
||||||
|
|
||||||
// payload and param bindings are dynamically allocated and declared at the end of the `binding` source file.
|
// payload and param bindings are dynamically allocated and declared at the end of the `binding` source file.
|
||||||
}
|
}
|
||||||
|
@ -161,6 +158,9 @@ func (c *Container) Handler(fn interface{}) context.Handler {
|
||||||
return makeHandler(fn, c)
|
return makeHandler(fn, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Struct accepts a pointer to a struct value and returns a structure which
|
||||||
|
// contains bindings for the struct's fields and a method to
|
||||||
|
// extract a Handler from this struct's method.
|
||||||
func (c *Container) Struct(ptrValue interface{}) *Struct {
|
func (c *Container) Struct(ptrValue interface{}) *Struct {
|
||||||
return makeStruct(ptrValue, c)
|
return makeStruct(ptrValue, c)
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,11 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
// DependencyHandler is the native function declaration which implementors should return a value match to an input.
|
||||||
DependencyHandler func(ctx context.Context, input *Input) (reflect.Value, error)
|
DependencyHandler func(ctx context.Context, input *Input) (reflect.Value, error)
|
||||||
|
// Dependency describes the design-time dependency to be injected at serve time.
|
||||||
|
// Contains its source location, the dependency handler (provider) itself and information
|
||||||
|
// such as static for static struct values or explicit to bind a value to its exact DestType and not if just assignable to it (interfaces).
|
||||||
Dependency struct {
|
Dependency struct {
|
||||||
OriginalValue interface{} // Used for debugging and for logging only.
|
OriginalValue interface{} // Used for debugging and for logging only.
|
||||||
Source Source
|
Source Source
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Source describes where a dependency is located at the source code itself.
|
||||||
type Source struct {
|
type Source struct {
|
||||||
File string
|
File string
|
||||||
Line int
|
Line int
|
||||||
|
|
|
@ -8,12 +8,19 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
// ErrorHandler describes an interface to handle errors per hero handler and its dependencies.
|
||||||
|
//
|
||||||
|
// Handles non-nil errors return from a hero handler or a controller's method (see `getBindingsFor` and `Handler`)
|
||||||
|
// the error may return from a request-scoped dependency too (see `Handler`).
|
||||||
ErrorHandler interface {
|
ErrorHandler interface {
|
||||||
HandleError(context.Context, error)
|
HandleError(context.Context, error)
|
||||||
}
|
}
|
||||||
|
// ErrorHandlerFunc implements the `ErrorHandler`.
|
||||||
|
// It describes the type defnition for an error function handler.
|
||||||
ErrorHandlerFunc func(context.Context, error)
|
ErrorHandlerFunc func(context.Context, error)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// HandleError fires when a non-nil error returns from a request-scoped dependency at serve-time or the handler itself.
|
||||||
func (fn ErrorHandlerFunc) HandleError(ctx context.Context, err error) {
|
func (fn ErrorHandlerFunc) HandleError(ctx context.Context, err error) {
|
||||||
fn(ctx, err)
|
fn(ctx, err)
|
||||||
}
|
}
|
||||||
|
@ -41,7 +48,7 @@ var (
|
||||||
ctx.StatusCode(DefaultErrStatusCode)
|
ctx.StatusCode(DefaultErrStatusCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.WriteString(err.Error())
|
_, _ = ctx.WriteString(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.StopExecution()
|
ctx.StopExecution()
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
package hero
|
package hero
|
||||||
|
|
||||||
import (
|
import (
|
||||||
stdContext "context"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/kataras/iris/v12/context"
|
"github.com/kataras/iris/v12/context"
|
||||||
"github.com/kataras/iris/v12/sessions"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func valueOf(v interface{}) reflect.Value {
|
func valueOf(v interface{}) reflect.Value {
|
||||||
|
@ -45,7 +42,6 @@ func isFunc(kindable interface{ Kind() reflect.Kind }) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
var inputTyp = reflect.TypeOf((*Input)(nil))
|
var inputTyp = reflect.TypeOf((*Input)(nil))
|
||||||
var timeTyp = reflect.TypeOf((*time.Time)(nil)).Elem()
|
|
||||||
|
|
||||||
var errTyp = reflect.TypeOf((*error)(nil)).Elem()
|
var errTyp = reflect.TypeOf((*error)(nil)).Elem()
|
||||||
|
|
||||||
|
@ -69,20 +65,6 @@ func isContext(typ reflect.Type) bool {
|
||||||
return typ.Implements(contextTyp)
|
return typ.Implements(contextTyp)
|
||||||
}
|
}
|
||||||
|
|
||||||
var stdContextTyp = reflect.TypeOf((*stdContext.Context)(nil)).Elem()
|
|
||||||
|
|
||||||
// isStdContext returns true if the "typ" is a type of standard Context.
|
|
||||||
func isStdContext(typ reflect.Type) bool {
|
|
||||||
return typ.Implements(stdContextTyp)
|
|
||||||
}
|
|
||||||
|
|
||||||
var sessionTyp = reflect.TypeOf((*sessions.Session)(nil))
|
|
||||||
|
|
||||||
// isStdContext returns true if the "typ" is a type of standard Context.
|
|
||||||
func isSession(typ reflect.Type) bool {
|
|
||||||
return typ == sessionTyp
|
|
||||||
}
|
|
||||||
|
|
||||||
var errorHandlerTyp = reflect.TypeOf((*ErrorHandler)(nil)).Elem()
|
var errorHandlerTyp = reflect.TypeOf((*ErrorHandler)(nil)).Elem()
|
||||||
|
|
||||||
func isErrorHandler(typ reflect.Type) bool {
|
func isErrorHandler(typ reflect.Type) bool {
|
||||||
|
|
|
@ -31,11 +31,13 @@ var sortByNumMethods Sorter = func(t1 reflect.Type, t2 reflect.Type) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Struct keeps a record of a particular struct value injection.
|
||||||
|
// See `Container.Struct` and `mvc#Application.Handle` methods.
|
||||||
type Struct struct {
|
type Struct struct {
|
||||||
ptrType reflect.Type
|
ptrType reflect.Type
|
||||||
ptrValue reflect.Value // the original ptr struct value.
|
ptrValue reflect.Value // the original ptr struct value.
|
||||||
elementType reflect.Type // the original struct type.
|
elementType reflect.Type // the original struct type.
|
||||||
bindings []*Binding // struct field bindings.
|
bindings []*binding // struct field bindings.
|
||||||
|
|
||||||
Container *Container
|
Container *Container
|
||||||
Singleton bool
|
Singleton bool
|
||||||
|
@ -102,6 +104,10 @@ func makeStruct(structPtr interface{}, c *Container) *Struct {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Acquire returns a struct value based on the request.
|
||||||
|
// If the dependencies are all static then these are already set-ed at the initialization of this Struct
|
||||||
|
// and the same struct value instance will be returned, ignoring the Context. Otherwise
|
||||||
|
// a new struct value with filled fields by its pre-calculated bindings will be returned instead.
|
||||||
func (s *Struct) Acquire(ctx context.Context) (reflect.Value, error) {
|
func (s *Struct) Acquire(ctx context.Context) (reflect.Value, error) {
|
||||||
if s.Singleton {
|
if s.Singleton {
|
||||||
ctx.Values().Set(context.ControllerContextKey, s.ptrValue)
|
ctx.Values().Set(context.ControllerContextKey, s.ptrValue)
|
||||||
|
@ -130,6 +136,8 @@ func (s *Struct) Acquire(ctx context.Context) (reflect.Value, error) {
|
||||||
return ctrl, nil
|
return ctrl, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MethodHandler accepts a "methodName" that should be a valid an exported
|
||||||
|
// method of the struct and returns its converted Handler.
|
||||||
func (s *Struct) MethodHandler(methodName string) context.Handler {
|
func (s *Struct) MethodHandler(methodName string) context.Handler {
|
||||||
m, ok := s.ptrValue.Type().MethodByName(methodName)
|
m, ok := s.ptrValue.Type().MethodByName(methodName)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
|
@ -2,15 +2,9 @@ package mvc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
"github.com/kataras/iris/v12/hero"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var baseControllerTyp = reflect.TypeOf((*BaseController)(nil)).Elem()
|
||||||
baseControllerTyp = reflect.TypeOf((*BaseController)(nil)).Elem()
|
|
||||||
errorHandlerTyp = reflect.TypeOf((*hero.ErrorHandler)(nil)).Elem()
|
|
||||||
errorTyp = reflect.TypeOf((*error)(nil)).Elem()
|
|
||||||
)
|
|
||||||
|
|
||||||
func isBaseController(ctrlTyp reflect.Type) bool {
|
func isBaseController(ctrlTyp reflect.Type) bool {
|
||||||
return ctrlTyp.Implements(baseControllerTyp)
|
return ctrlTyp.Implements(baseControllerTyp)
|
||||||
|
@ -26,33 +20,3 @@ func indirectType(typ reflect.Type) reflect.Type {
|
||||||
}
|
}
|
||||||
return typ
|
return typ
|
||||||
}
|
}
|
||||||
|
|
||||||
func isErrorHandler(ctrlTyp reflect.Type) bool {
|
|
||||||
return ctrlTyp.Implements(errorHandlerTyp)
|
|
||||||
}
|
|
||||||
|
|
||||||
func hasErrorOutArgs(fn reflect.Method) bool {
|
|
||||||
n := fn.Type.NumOut()
|
|
||||||
if n == 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
if out := fn.Type.Out(i); out.Kind() == reflect.Interface {
|
|
||||||
if out.Implements(errorTyp) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func getInputArgsFromFunc(funcTyp reflect.Type) []reflect.Type {
|
|
||||||
n := funcTyp.NumIn()
|
|
||||||
funcIn := make([]reflect.Type, n)
|
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
funcIn[i] = funcTyp.In(i)
|
|
||||||
}
|
|
||||||
return funcIn
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user