习惯了这种格式的返回值:
{
"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": {}
}