iris icon indicating copy to clipboard operation
iris copied to clipboard

[BUG]`hero.Resulthandler` can only handle custom struct

Open dydhyhwu opened this issue 1 year ago • 2 comments

hero.ResultHandler can only handle cases where the return value is a custom struct or dispatcher. After reviewing the code, I found that before ResultHandler processing, it needs to go through dispatchFuncResult processing, and then dispatchCommon decides whether to call handlers. I would like to know why it was designed this way.

In scenarios where Container is used to uniformly handle return values, I hope that the return values of all Handlers are uniformly wrapped and processed, so that a unified return value structure can be obtained. However, the framework has specialized handling for some basic types, which forces me to call ctx.JSON(map[string]interface{} {...}) in some handlers.

The code and expected result I hope to achieve is as follows:

type Response struct {
	Code int         `json:"code"`
	Data interface{} `json:"data,omitempty"`
	Msg  string      `json:"msg,omitempty"`
}

type testOutput struct {
	ID   int    `json:"id"`
	Name string `json:"name"`
}

func resultFormatter(next hero.ResultHandler) hero.ResultHandler {
	return func(ctx iris.Context, v interface{}) error {
		log.Infof("use result handler\n")

		return next(ctx, map[string]interface{}{
			"code": 200,
			"data": v,
			"msg":  "",
		})
	}
}

func emptyResHandler(ctx iris.Context) {
	log.Info("hello")
}

func boolResHandler(ctx iris.Context) bool {
	return true
}

func stringResHandler(ctx iris.Context) string {
	return "hello"
}

func intResHandler(ctx iris.Context) int {
	return 1
}

func int64ResHandler(ctx iris.Context) int64 {
	return 1
}

func structResHandler(ctx iris.Context) testOutput {
	return testOutput{
		ID:   1,
		Name: "hello",
	}
}

func configureApi(api *iris.APIContainer) {
	api.UseResultHandler(resultFormatter)
	api.Get("/empty", emptyResHandler)
	api.Get("/bool", boolResHandler)
	api.Get("/string", stringResHandler)
	api.Get("/int", intResHandler)
	api.Get("/int64", int64ResHandler)
	api.Get("/struct", structResHandler)
}

when the return value is empty, the expected result is:

{
    "code": 200,
    "data": null,
    "msg": ""
}

when the return value is string, the expected result is:

{
    "code": 200,
    "data": "string",
    "msg": ""
}

when the return value is custom struct, the expected result is :

{
    "code": 200,
    "data": {
        "id": 1,
        "name": "test"
    },
    "msg": ""
}

and so on...

dydhyhwu avatar Apr 22 '24 08:04 dydhyhwu

related code: https://github.com/kataras/iris/blob/b904793278a3241da109503f127cdb8aed8e9e34/hero/func_result.go#L264-L331

https://github.com/kataras/iris/blob/b904793278a3241da109503f127cdb8aed8e9e34/hero/func_result.go#L366-L373

dydhyhwu avatar Apr 22 '24 08:04 dydhyhwu

@kataras need some help

dydhyhwu avatar Apr 24 '24 16:04 dydhyhwu