Skip to content

Commit

Permalink
add support for mvc and hero dynamic dependencies to understand the e…
Browse files Browse the repository at this point in the history
…rror type as a second output value as requested at: kataras#1187

Former-commit-id: 49e29c06aaaa22743354981342c29fc9d5953d0e
  • Loading branch information
kataras committed Feb 15, 2019
1 parent 07994ad commit 9cfaff0
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 11 deletions.
39 changes: 29 additions & 10 deletions hero/di/object.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,10 @@ func MakeReturnValue(fn reflect.Value, goodFunc TypeChecker) (func([]reflect.Val
return nil, typ, errBad
}

// invalid if not returns one single value.
if typ.NumOut() != 1 {
n := typ.NumOut()

// invalid if not returns one single value or two values but the second is not an error.
if !(n == 1 || (n == 2 && IsError(typ.Out(1)))) {
return nil, typ, errBad
}

Expand All @@ -88,19 +90,36 @@ func MakeReturnValue(fn reflect.Value, goodFunc TypeChecker) (func([]reflect.Val
}
}

outTyp := typ.Out(0)
zeroOutVal := reflect.New(outTyp).Elem()
firstOutTyp := typ.Out(0)
firstZeroOutVal := reflect.New(firstOutTyp).Elem()

bf := func(ctxValue []reflect.Value) reflect.Value {
results := fn.Call(ctxValue)
if len(results) == 0 {
return zeroOutVal
}

v := results[0]
if !v.IsValid() {
return zeroOutVal
if !v.IsValid() { // check the first value, second is error.
return firstZeroOutVal
}

if n == 2 {
// two, second is always error.
errVal := results[1]
if !errVal.IsNil() {
// error is not nil, do something with it.
if ctx, ok := ctxValue[0].Interface().(interface {
StatusCode(int)
WriteString(string) (int, error)
StopExecution()
}); ok {
ctx.StatusCode(400)
ctx.WriteString(errVal.Interface().(error).Error())
ctx.StopExecution()
}

return firstZeroOutVal
}
}

// if v.String() == "<interface {} Value>" {
// println("di/object.go: " + v.String())
// // println("di/object.go: because it's interface{} it should be returned as: " + v.Elem().Type().String() + " and its value: " + v.Elem().Interface().(string))
Expand All @@ -109,7 +128,7 @@ func MakeReturnValue(fn reflect.Value, goodFunc TypeChecker) (func([]reflect.Val
return v
}

return bf, outTyp, nil
return bf, firstOutTyp, nil
}

// IsAssignable checks if "to" type can be used as "b.Value/ReturnValue".
Expand Down
7 changes: 7 additions & 0 deletions hero/di/reflect.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,13 @@ func IsZero(v reflect.Value) bool {
return v.Interface() == zero.Interface()
}

var errTyp = reflect.TypeOf((*error)(nil)).Elem()

// IsError returns true if "typ" is type of `error`.
func IsError(typ reflect.Type) bool {
return typ.Implements(errTyp)
}

// IndirectValue returns the reflect.Value that "v" points to.
// If "v" is a nil pointer, Indirect returns a zero Value.
// If "v" is not a pointer, Indirect returns v.
Expand Down
4 changes: 4 additions & 0 deletions mvc/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,10 @@ func (c *ControllerActivator) handlerOf(m reflect.Method, funcDependencies []ref
in[0] = ctrl
funcInjector.Inject(&in, ctxValue)

if ctx.IsStopped() {
return // stop as soon as possible, although it would stop later on if `ctx.StopExecution` called.
}

// for idxx, inn := range in {
// println("controller.go: execution: in.Value = "+inn.String()+" and in.Type = "+inn.Type().Kind().String()+" of index: ", idxx)
// }
Expand Down
17 changes: 17 additions & 0 deletions mvc/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -272,11 +272,22 @@ type testControllerBindDeep struct {
testControllerBindStruct
}

func (t *testControllerBindDeep) BeforeActivation(b BeforeActivation) {
b.Dependencies().Add(func(ctx iris.Context) (v testCustomStruct, err error) {
err = ctx.ReadJSON(&v)
return
})
}

func (t *testControllerBindDeep) Get() {
// t.testControllerBindStruct.Get()
t.Ctx.Writef(t.TitlePointer.title + t.TitleValue.title + t.Other)
}

func (t *testControllerBindDeep) Post(v testCustomStruct) string {
return v.Name
}

func TestControllerDependencies(t *testing.T) {
app := iris.New()
// app.Logger().SetLevel("debug")
Expand All @@ -299,6 +310,12 @@ func TestControllerDependencies(t *testing.T) {

e.GET("/deep").Expect().Status(iris.StatusOK).
Body().Equal(expected)

e.POST("/deep").WithJSON(iris.Map{"name": "kataras"}).Expect().Status(iris.StatusOK).
Body().Equal("kataras")

e.POST("/deep").Expect().Status(iris.StatusBadRequest).
Body().Equal("unexpected end of JSON input")
}

type testCtrl0 struct {
Expand Down
2 changes: 1 addition & 1 deletion websocket/connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -808,7 +808,7 @@ func DialContext(ctx stdContext.Context, url string, cfg ConnectionConfig) (Clie
ctx = stdContext.Background()
}

if !strings.HasPrefix(url, "ws://") {
if !strings.HasPrefix(url, "ws://") || !strings.HasPrefix(url, "wss://") {
url = "ws://" + url
}

Expand Down

0 comments on commit 9cfaff0

Please sign in to comment.