引言
业务实现过程中,一般会形成约定俗成的一些默认格式,前后端对于接口格式的约定,多服务之间的接口交互格式等等。所以需要对于接口进行返回格式进行自定义实现。
go-kratos 接口返回格式
默认格式:
{
// 错误码,跟 http-status 一致,并且在 grpc 中可以转换成 grpc-status
"code": 500,
// 错误原因,定义为业务判定错误码
"reason": "USER_NOT_FOUND",
// 错误信息,为用户可读的信息,可作为用户提示内容
"message": "invalid argument error",
// 错误元信息,为错误添加附加可扩展信息
"metadata": {
"foo": "bar"
}
}
相关实现规范
自定义实现
自定义格式如下:
// httpResponse 响应结构体
type httpResponse struct {
Code int `json:"code"`
Message string `json:"message"`
Data interface{} `json:"data"`
}
接口响应:即http响应状态码为 200 时的实现
// EncoderResponse 请求响应封装
func EncoderResponse() http.EncodeResponseFunc {
return func(w stdhttp.ResponseWriter, request *stdhttp.Request, i interface{}) error {
if i == nil {
return nil
}
resp := &httpResponse{
Code: stdhttp.StatusOK,
Message: "",
Data: i,
}
codec := encoding.GetCodec("json")
data, err := codec.Marshal(resp)
if err != nil {
return err
}
w.Header().Set("Content-Type", "application/json")
_, err = w.Write(data)
if err != nil {
return err
}
return nil
}
}
错误响应:即对于error的处理响应
// EncoderError 错误响应封装
func EncoderError() http.EncodeErrorFunc {
return func(w stdhttp.ResponseWriter, r *stdhttp.Request, err error) {
if err == nil {
return
}
se := &httpResponse{}
gs, ok := status.FromError(err)
if !ok {
se = &httpResponse{Code: stdhttp.StatusInternalServerError}
}
se = &httpResponse{
Code: httpstatus.FromGRPCCode(gs.Code()),
Message: gs.Message(),
Data: nil,
}
codec, _ := http.CodecForRequest(r, "Accept")
body, err := codec.Marshal(se)
if err != nil {
w.WriteHeader(stdhttp.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/"+codec.Name())
w.WriteHeader(se.Code)
_, _ = w.Write(body)
}
}
server引入
// 请求响应封装
opts = append(opts, http.ResponseEncoder(EncoderResponse()))
// 错误响应封装`
opts = append(opts, http.ErrorEncoder(EncoderError()))
srv := http.NewServer(opts...)