Closed majintao closed 3 years ago
可以在 errorsEncoder 处理
应该也可以 errors.New(200, reason,msg)
可以自定义错误,例如: errors.New(10003, message)
我是定义了统一的http返回结构体
type Response struct {
Code int `json:"code" form:"code"`
Message string `json:"message" form:"message"`
Ts string `json:"ts" form:"ts"`
Reason string `json:"reason" form:"reason"`
Data interface{} `json:"data" form:"data"`
}
然后重写 ErrorEncoder
func ErrorEncoder(w stdHttp.ResponseWriter, r *stdHttp.Request, err error) {
se := errors.FromError(err)
reply := NewResponse()
reply.Code = int(se.Code)
reply.Data = nil
reply.Message = se.Message
reply.Reason = se.Reason
reply.Ts = time.Now().Format(pkgTime.MilliTimeLayout)
codec, _ := http.CodecForRequest(r, "Accept")
body, err := codec.Marshal(reply)
if err != nil {
w.WriteHeader(stdHttp.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", contentType(codec.Name()))
w.WriteHeader(stdHttp.StatusOK)
w.Write(body)
}
再重写 ResponseEncoder
func ResponseEncoder(w stdHttp.ResponseWriter, r *stdHttp.Request, v interface{}) error {
reply := NewResponse()
reply.Code = 200
reply.Data = v
reply.Message = "success"
reply.Reason = "success"
reply.Ts = time.Now().Format(pkgTime.MilliTimeLayout)
codec, _ := http.CodecForRequest(r, "Accept")
data, err := codec.Marshal(reply)
if err != nil {
return err
}
w.Header().Set("Content-Type", contentType(codec.Name()))
w.WriteHeader(stdHttp.StatusOK)
w.Write(data)
return nil
}
最后注入到http server中
// 错误解码器
opts = append(opts, http.ErrorEncoder(Encoder.ErrorEncoder))
// 返回参数解码器
opts = append(opts, http.ResponseEncoder(Encoder.ResponseEncoder))
@chenyue233
能贴一下完整的demo么。。有几个函数没有
@chenyue233 能贴一下完整的demo么。。有几个函数没有
pkgTime.MilliTimeLayout 是 2006-01-02 15:04:05.00000 , stdHttp.StatusInternalServerError 是标准库的,contentType(codec.Name())是从kratos的httputils拷出来的 具体内容是 func ContentType(subtype string) string { return strings.Join([]string{baseContentType, subtype}, "/") }。我是重写业务需要和之前的接口保持一致,不是最佳实践。
我是定义了统一的http返回结构体
type Response struct { Code int `json:"code" form:"code"` Message string `json:"message" form:"message"` Ts string `json:"ts" form:"ts"` Reason string `json:"reason" form:"reason"` Data interface{} `json:"data" form:"data"` }
然后重写 ErrorEncoder
func ErrorEncoder(w stdHttp.ResponseWriter, r *stdHttp.Request, err error) { se := errors.FromError(err) reply := NewResponse() reply.Code = int(se.Code) reply.Data = nil reply.Message = se.Message reply.Reason = se.Reason reply.Ts = time.Now().Format(pkgTime.MilliTimeLayout) codec, _ := http.CodecForRequest(r, "Accept") body, err := codec.Marshal(reply) if err != nil { w.WriteHeader(stdHttp.StatusInternalServerError) return } w.Header().Set("Content-Type", contentType(codec.Name())) w.WriteHeader(stdHttp.StatusOK) w.Write(body) }
再重写 ResponseEncoder
func ResponseEncoder(w stdHttp.ResponseWriter, r *stdHttp.Request, v interface{}) error { reply := NewResponse() reply.Code = 200 reply.Data = v reply.Message = "success" reply.Reason = "success" reply.Ts = time.Now().Format(pkgTime.MilliTimeLayout) codec, _ := http.CodecForRequest(r, "Accept") data, err := codec.Marshal(reply) if err != nil { return err } w.Header().Set("Content-Type", contentType(codec.Name())) w.WriteHeader(stdHttp.StatusOK) w.Write(data) return nil }
最后注入到http server中
// 错误解码器 opts = append(opts, http.ErrorEncoder(Encoder.ErrorEncoder)) // 返回参数解码器 opts = append(opts, http.ResponseEncoder(Encoder.ResponseEncoder))
这样子做会有一个问题,omitempty在json的序列化中会生效,导致默认值的数据返回并不完整
我是定义了统一的http返回结构体
type Response struct { Code int `json:"code" form:"code"` Message string `json:"message" form:"message"` Ts string `json:"ts" form:"ts"` Reason string `json:"reason" form:"reason"` Data interface{} `json:"data" form:"data"` }
然后重写 ErrorEncoder
func ErrorEncoder(w stdHttp.ResponseWriter, r *stdHttp.Request, err error) { se := errors.FromError(err) reply := NewResponse() reply.Code = int(se.Code) reply.Data = nil reply.Message = se.Message reply.Reason = se.Reason reply.Ts = time.Now().Format(pkgTime.MilliTimeLayout) codec, _ := http.CodecForRequest(r, "Accept") body, err := codec.Marshal(reply) if err != nil { w.WriteHeader(stdHttp.StatusInternalServerError) return } w.Header().Set("Content-Type", contentType(codec.Name())) w.WriteHeader(stdHttp.StatusOK) w.Write(body) }
再重写 ResponseEncoder
func ResponseEncoder(w stdHttp.ResponseWriter, r *stdHttp.Request, v interface{}) error { reply := NewResponse() reply.Code = 200 reply.Data = v reply.Message = "success" reply.Reason = "success" reply.Ts = time.Now().Format(pkgTime.MilliTimeLayout) codec, _ := http.CodecForRequest(r, "Accept") data, err := codec.Marshal(reply) if err != nil { return err } w.Header().Set("Content-Type", contentType(codec.Name())) w.WriteHeader(stdHttp.StatusOK) w.Write(data) return nil }
最后注入到http server中
// 错误解码器 opts = append(opts, http.ErrorEncoder(Encoder.ErrorEncoder)) // 返回参数解码器 opts = append(opts, http.ResponseEncoder(Encoder.ResponseEncoder))
@chenyue233 这个样子的话 openapi 是怎么处理的呀 ?
应该也可以 errors.New(200, reason,msg)
grpc传输这个 errors 200;client端会接受错误 打印EOF错误
Bot detected the issue body's language is not English, translate it automatically. 👯👭🏻🧑🤝🧑👫🧑🏿🤝🧑🏻👩🏾🤝👨🏿👬🏿
should also work errors.New(200, reason, msg)
grpc transmits this errors 200; the client side will accept the error and print EOF error
可以自定义错误,例如: errors.New(10003, message)
状态码设置 不能大于600;因为这里映射的是htp的状态码
Bot detected the issue body's language is not English, translate it automatically. 👯👭🏻🧑🤝🧑👫🧑🏿🤝🧑🏻👩🏾🤝👨🏿👬🏿
Errors can be customized, for example: errors.New(10003, message)
The status code setting cannot be greater than 600; because the status code of http is mapped here
@chenyue233 能贴一下完整的demo么。。有几个函数没有
把上面那个朋友的代码整理了下, 记录一下
internal/server/http.go
func NewHTTPServer(c *conf.Server, ac *conf.Auth, logger log.Logger, s *service.PassportLoginService) *http.Server {
var opts = []http.ServerOption{
http.Middleware(
recovery.Recovery(),
logging.Server(logger),
),
http.Filter(handlers.CORS(
handlers.AllowedHeaders([]string{"X-Requested-With", "Content-Type", "Authorization"}),
handlers.AllowedMethods([]string{"GET", "POST", "PUT", "HEAD", "OPTIONS"}),
handlers.AllowedOrigins([]string{"*"}),
)),
}
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(ResponseEncoder))
opts = append(opts, http.ErrorEncoder(ErrorEncoder))
srv := http.NewServer(opts...)
v1.RegisterHTTPServer(srv, s)
return srv
}
新建一个 http_encoder.go 文件 internal/server/http_encoder.go
package server
import (
"net/http"
"strings"
"time"
"github.com/go-kratos/kratos/v2/errors"
khttp "github.com/go-kratos/kratos/v2/transport/http"
)
type Response struct {
Code int `json:"code" form:"code"`
Message string `json:"message" form:"message"`
Ts string `json:"ts" form:"ts"`
Data interface{} `json:"data" form:"data"`
}
type ErrResponse struct {
Code int `json:"code" form:"code"`
Message string `json:"message" form:"message"`
Ts string `json:"ts" form:"ts"`
Reason string `json:"reason" form:"reason"`
Data interface{} `json:"data" form:"data"`
}
func ErrorEncoder(w http.ResponseWriter, r *http.Request, err error) {
se := errors.FromError(err)
reply := &ErrResponse{}
reply.Code = int(se.Code)
reply.Data = nil
reply.Message = se.Message
reply.Reason = se.Reason
reply.Ts = time.Now().Format("2006-01-02 15:04:05.00000")
codec, _ := khttp.CodecForRequest(r, "Accept")
body, err := codec.Marshal(reply)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", strings.Join([]string{"application", codec.Name()}, "/"))
w.WriteHeader(http.StatusOK)
w.Write(body)
}
func ResponseEncoder(w http.ResponseWriter, r *http.Request, v interface{}) error {
reply := &Response{}
reply.Code = 0
reply.Data = v
reply.Message = "ok"
reply.Ts = time.Now().Format("2006-01-02 15:04:05.00000")
codec, _ := khttp.CodecForRequest(r, "Accept")
data, err := codec.Marshal(reply)
if err != nil {
return err
}
w.Header().Set("Content-Type", strings.Join([]string{"application", codec.Name()}, "/"))
w.WriteHeader(http.StatusOK)
w.Write(data)
return nil
}
比如:业务状态码10003,请求http-status 又要是200 的情况