kratos的返回值问题与错误返回问题

习惯了这种格式的返回值:

{
	"code":"0",
	"message":"成功"
    "captchaId": "0TFqCFHqeGuvYFy3EajN",
    ...
}

今天按照kratos写api发现返回的是这种

{
    "captchaId": "0TFqCFHqeGuvYFy3EajN",
    "captcha": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPAAAABQCAMAAAAQlwhOAAAA81BMVEUAAAAmLVKIj7QKETYHDjOWncIECzAvNluAh6ynrtM0O2CaocZ6gaZPVnt9hKllbJEuNVoYH0QpMFUECzCjqs8sM1hVXIETGj97gqdDSm+XnsMNFDkRGD19hKkCCS4KETYOFTpzep9vdptOVXo7QmeqsdaDiq8AByxrcpdudZodJEkZIEUZIEWPlrssM1hxeJ1QV3x4f6QcI0ior9QlLFF6gaYKETaFjLFDSm9eZYo6QWYfJkt9hKmaocZaYYaDiq+Yn8Sjqs8gJ0woL1R7gqeVnMGRmL1YX4SLkrdbYoctNFmPlrsBCC0mLVIvNltOVXqZoMUuqQojAAAAAXRSTlMAQObYZgAABItJREFUeJzsnHtLIz0UxhNUttJCKVWk7qjUtYJI/1EEq1YUlFpZv//XeZlMZnKZ2zlJTmb03Ydltk5zOT+fTK6tjELHJKX2V8fH34P4KlhJ4Xlfg5fI2NUVhPgPQc3ten2tI04Ye3QtFcT7pyPimvtJkjw+OhND1A1vvXwc9tGii0oD66Tl/TP1crJYLBj7TR0RrU5OmonPzgriyWSS8v6mIv5FVO7G/BHjsLiS8f6iId5sNvDEf0lCqJHFuxOqXAzv36jERnPb2QlGjFAN7wVRdUaHQsJ77pTr4oKMmKjcXOfnjsTBI2F7YYq5aXnfjZdAe3tBiG9u2oh7o0gO6zoEpOlNiwigw8N2Ytdn3lmkC4YeOmwsCalmnr2Szks086zWS8S66hSV9yUwMeTx6VQvYZ9eSAepxBnjPL3GVOD+GcWbwvLs6l3xFzhlIy9iAeYgzgUuDwD99QUnbhBqiY2VSZv+56J9+b/iffIJitThFJMxP4v39/etO09PXsSMYOhSXnJ5zaEdZPN6Osz8hi7hYdZycyjBVcbj0m9IoY6NHy4n3mLI4fIH1WJlwNzAls0aWLjMdwpKPU4vt7jwkZKm1jqcKFT1AtpxZanS6+kphHg8HjN2e0tGLMNucJglSaI7zM2csDpEPov3sjo1yGGj5gE4DBly7nCdEiNT4TKm41JjWqHLyxrixni5Ph3INBgM5I3s98C1f9poqtooOOoZk+XlJaC6I65dhcC8fK1FWSomc1ii8vyJLB5PlZhjx5bZbJZnLPIjsitr4DmyTOv1uslhdQPiMFBTVjjMVOWijHdUQbzhEeLGa5VKObxlda0K4DBG0+nUCqr4tb2/I4lVJ8nVkMds85hKpeLdbrf42N00VeHyPA45KcHxMt1hNanRnCjmcxXtIBqvEay2gCjGWHQxIIdJ9IBLrnUTjGvzCqe6LYeLm5R6eHAl1u/kyKTBOu0V75buIHm1/sqab/O2+YvSNbpOe68Yqt3dMrGTSrsAucMrwJB3fe1G3PDetO6NQLypltYugABdrVaArE68TVLDJlzYTablclll5mqOntSEEIB3bP4ottVgC1apZdaurY5qPp9jCoknsezUlfKCFqya7P46VU95Sw4LIXkR2wDRRHiWcieu+HUIqXBnKSjd3UlizGyjtXv2PogmdxhlcesA3DS5eEPE5q2jhvcwbdrD4be3iMRHR4L4g1VNl92f4iFq98Dgpf78dMb78VG1MHI+WRsOh8buQVMzsiQ+P00v4bBNXDUWA2U6LJsRTDE/IW8uzqtmW45C8EYV1w8PPfz9RtKPTLsBxm3h+8s4e+oAGHto4S/N4VBPMEoReeXBlWlxvOqjazBQR3XdGRxTwKPJPmnUdQAg3ZfuPGuvMftRo9EIfQJGpfqTk/t7m/j5WRHjPuYleJEnYDRqOhvzdLj0LTYM7yciLU4hz8aM7Smv7yl+ftIRh5O1Aen1PcUueQ/AKdEbkL3UwQGc+GfoB/FCu81v/r3wQtCBMcD3wsP9/RAvRXMY9vdDfpL+b7z/9E9B9V8AAAD//3xxQkVwT1uqAAAAAElFTkSuQmCC"
}

可以在http中添加方法,统一添加业务成功代码

package server

import (
	"github.com/go-kratos/kratos/v2/encoding"
	"github.com/go-kratos/kratos/v2/log"
	"github.com/go-kratos/kratos/v2/middleware/logging"
	mmd "github.com/go-kratos/kratos/v2/middleware/metadata"
	"github.com/go-kratos/kratos/v2/middleware/metrics"
	"github.com/go-kratos/kratos/v2/middleware/recovery"
	"github.com/go-kratos/kratos/v2/middleware/validate"
	"github.com/go-kratos/kratos/v2/transport/http"
	"github.com/go-kratos/swagger-api/openapiv2"
	baseHttp "kratosadmin/api/base/v1"
	userHttp "kratosadmin/api/user/v1"
	"kratosadmin/app/user/service/internal/conf"
	"kratosadmin/app/user/service/internal/service"
	"kratosadmin/app/user/service/middleware"
	httpNet "net/http"
	"time"
)

// NewHTTPServer new a HTTP server.
func NewHTTPServer(c *conf.Server, userService *service.UserService, baseService *service.BaseService, logger log.Logger, middleware2 middleware.Middleware) *http.Server {
	var opts = []http.ServerOption{
		http.Middleware(
			recovery.Recovery(),
			logging.Server(logger),
			metrics.Server(),
			validate.Validator(),
			mmd.Server(),
			middleware2.Auth(),
		),
		http.Filter(middleware2.Cors()),
	}
	if c.Http.Network != "" {
		opts = append(opts, http.Network(c.Http.Network))
	}
	if c.Http.Addr != "" {
		opts = append(opts, http.Address(c.Http.Addr))
	}

	if c.Http.Timeout != nil {
		opts = append(opts, http.Timeout(c.Http.Timeout.AsDuration()))
	}
	opts = append(opts, http.ResponseEncoder(func(
		w httpNet.ResponseWriter,
		r *httpNet.Request,
		i interface{},
	) error {
		type response struct {
			Code int
			Data interface{}
			Ts   string
		}
		reply := &response{
			Code: 200,
			Data: i,
			Ts:   time.Now().String(),
		}
		codec := encoding.GetCodec("json")
		data, err := codec.Marshal(reply)
		if err != nil {
			return err
		}
		w.Header().Set("Content-Type", "application/json")
		w.Write(data)
		return nil
	}))

	srv := http.NewServer(opts...)

	//user服务
	userHttp.RegisterUserHTTPServer(srv, userService)
	//基础服务
	baseHttp.RegisterBaseHTTPServer(srv, baseService)
	openAPIhandler := openapiv2.NewHandler()
	srv.HandlePrefix("/q/", openAPIhandler)
	return srv
}

返回值就变成了下面的了,复合要求
资料来源:https://mp.weixin.qq.com/s/4ocdoAVXXKTvJ3U65YXltw

{
    "Code": 200,
    "Data": {
        "captchaId": "NYAa3oSuojuvzBFvCX7u",
        "captcha": "data:image/png;base64,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"
    },
    "Ts": "2021-09-22 14:48:21.9387671 +0800 CST m=+0.239897501"
}

然后,貌似还有一种哲学,既然正常返回http状态吗为200,那么返回体内容就应该是业务数据不应该再加载业务code/message等,所以kratos默认返回的符合这个逻辑,那么错误消息怎么返回呢?比如400错误、500错误呢,为什么这么设计,业务code与http code一致呢?可以方便运维抓取接口状态数据吧
链接地址:https://go-kratos.dev/docs/component/errors

可以这样自定义错误

// 通过 errors.New() 响应错误
	err = errors.New(500, "USER_NAME_EMPTY", "user name is empty")

也可以这样:

// 通过 proto 生成的代码响应错误,并且包名应替换为自己生成代码后的 package name
	err = v1.ErrorUsernameConflict("user %s not found", "kratos")

覆盖返回错误码即可,比如这样返回结果

{
    "code": 409,
    "reason": "USERNAME_CONFLICT",
    "message": "user kratos not found",
    "metadata": {}
}
上一篇:这几个用 Pyecharts 做出来的交互图表,领导说叼爆了!


下一篇:第2天 | 3天搞定Pyecharts数据分析,主题样式