mirror of
https://github.com/kataras/iris.git
synced 2025-12-17 09:57:01 +00:00
Former-commit-id: 2b48b9b912e9eb8f5f2c6d413907dbfdae857e08
This commit is contained in:
@@ -73,6 +73,7 @@ func IndirectValue(v reflect.Value) reflect.Value {
|
||||
if k := v.Kind(); k == reflect.Ptr { //|| k == reflect.Interface {
|
||||
return v.Elem()
|
||||
}
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
@@ -106,6 +107,17 @@ func IndirectType(typ reflect.Type) reflect.Type {
|
||||
return typ
|
||||
}
|
||||
|
||||
// IsNil same as `reflect.IsNil` but a bit safer to use, returns false if not a correct type.
|
||||
func IsNil(v reflect.Value) bool {
|
||||
k := v.Kind()
|
||||
switch k {
|
||||
case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.UnsafePointer, reflect.Interface, reflect.Slice:
|
||||
return v.IsNil()
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func goodVal(v reflect.Value) bool {
|
||||
switch v.Kind() {
|
||||
case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Slice:
|
||||
|
||||
@@ -211,7 +211,6 @@ func DispatchFuncResult(ctx context.Context, errorHandler ErrorHandler, values [
|
||||
)
|
||||
|
||||
for _, v := range values {
|
||||
|
||||
// order of these checks matters
|
||||
// for example, first we need to check for status code,
|
||||
// secondly the string (for content type and content)...
|
||||
@@ -310,27 +309,46 @@ func DispatchFuncResult(ctx context.Context, errorHandler ErrorHandler, values [
|
||||
// it's raw content, get the latest
|
||||
content = value
|
||||
case compatibleErr:
|
||||
if value != nil { // it's always not nil but keep it here.
|
||||
if errorHandler != nil {
|
||||
errorHandler.HandleError(ctx, value)
|
||||
break
|
||||
}
|
||||
|
||||
err = value
|
||||
if statusCode < 400 {
|
||||
statusCode = DefaultErrStatusCode
|
||||
}
|
||||
break // break on first error, error should be in the end but we
|
||||
// need to know break the dispatcher if any error.
|
||||
// at the end; we don't want to write anything to the response if error is not nil.
|
||||
if value == nil || di.IsNil(v) {
|
||||
continue
|
||||
}
|
||||
|
||||
if errorHandler != nil {
|
||||
errorHandler.HandleError(ctx, value)
|
||||
break
|
||||
}
|
||||
|
||||
err = value
|
||||
if statusCode < 400 {
|
||||
statusCode = DefaultErrStatusCode
|
||||
}
|
||||
break // break on first error, error should be in the end but we
|
||||
// need to know break the dispatcher if any error.
|
||||
// at the end; we don't want to write anything to the response if error is not nil.
|
||||
|
||||
default:
|
||||
// else it's a custom struct or a dispatcher, we'll decide later
|
||||
// because content type and status code matters
|
||||
// do that check in order to be able to correctly dispatch:
|
||||
// (customStruct, error) -> customStruct filled and error is nil
|
||||
if custom == nil && f != nil {
|
||||
custom = f
|
||||
if custom == nil {
|
||||
// if it's a pointer to struct/map.
|
||||
|
||||
if di.IsNil(v) {
|
||||
// if just a ptr to struct with no content type given
|
||||
// then try to get the previous response writer's content type,
|
||||
// and if that is empty too then force-it to application/json
|
||||
// as the default content type we use for structs/maps.
|
||||
contentType = ctx.GetContentType()
|
||||
if contentType == "" {
|
||||
contentType = context.ContentJSONHeaderValue
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if value != nil {
|
||||
custom = value // content type will be take care later on.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ func GetCustomStructWithContentType() (testCustomStruct, string) {
|
||||
return testCustomStruct{"Iris", 2}, "text/xml"
|
||||
}
|
||||
|
||||
func GetCustomStructWithError(ctx iris.Context) (s testCustomStruct, err error) {
|
||||
func GetCustomStructWithError(ctx context.Context) (s testCustomStruct, err error) {
|
||||
s = testCustomStruct{"Iris", 2}
|
||||
if ctx.URLParamExists("err") {
|
||||
err = errors.New("omit return of testCustomStruct and fire error")
|
||||
@@ -86,7 +86,7 @@ type err struct {
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
func (e err) Dispatch(ctx iris.Context) {
|
||||
func (e err) Dispatch(ctx context.Context) {
|
||||
// write the status code based on the err's StatusCode.
|
||||
ctx.StatusCode(e.Status)
|
||||
// send to the client the whole object as json
|
||||
@@ -97,6 +97,22 @@ func GetCustomErrorAsDispatcher() err {
|
||||
return err{iris.StatusBadRequest, "this is my error as json"}
|
||||
}
|
||||
|
||||
func GetCustomTypedNilEmptyResponse() iris.Map {
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetCustomTypedPtrNilEmptyResponse() *iris.Map {
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetCustomMapNilEmptyResponse() map[string]interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetCustomPtrStructNilEmptyResponse() *testCustomStruct {
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestFuncResult(t *testing.T) {
|
||||
app := iris.New()
|
||||
h := New()
|
||||
@@ -120,6 +136,11 @@ func TestFuncResult(t *testing.T) {
|
||||
app.Get("/custom/struct/with/error", h.Handler(GetCustomStructWithError))
|
||||
app.Get("/custom/error/as/dispatcher", h.Handler(GetCustomErrorAsDispatcher))
|
||||
|
||||
app.Get("/custom/nil/typed", h.Handler(GetCustomTypedNilEmptyResponse))
|
||||
app.Get("/custom/nil/typed/ptr", h.Handler(GetCustomTypedPtrNilEmptyResponse))
|
||||
app.Get("/custom/nil/map", h.Handler(GetCustomMapNilEmptyResponse))
|
||||
app.Get("/custom/nil/struct", h.Handler(GetCustomPtrStructNilEmptyResponse))
|
||||
|
||||
e := httptest.New(t, app)
|
||||
|
||||
e.GET("/text").Expect().Status(iris.StatusOK).
|
||||
@@ -172,4 +193,14 @@ func TestFuncResult(t *testing.T) {
|
||||
// the content should be not JSON it should be the status code's text
|
||||
// it will fire the error's text
|
||||
JSON().Equal(err{iris.StatusBadRequest, "this is my error as json"})
|
||||
|
||||
// its result is nil should give an empty response but content-type is set correctly.
|
||||
e.GET("/custom/nil/typed").Expect().
|
||||
Status(iris.StatusOK).ContentType(context.ContentJSONHeaderValue).Body().Empty()
|
||||
e.GET("/custom/nil/typed/ptr").Expect().
|
||||
Status(iris.StatusOK).ContentType(context.ContentJSONHeaderValue).Body().Empty()
|
||||
e.GET("/custom/nil/map").Expect().
|
||||
Status(iris.StatusOK).ContentType(context.ContentJSONHeaderValue).Body().Empty()
|
||||
e.GET("/custom/nil/struct").Expect().
|
||||
Status(iris.StatusOK).ContentType(context.ContentJSONHeaderValue).Body().Empty()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user