自定义响应

目标编码
我们需要额外返回状态码和信息。
我们可以覆盖默认的 DefaultResponseEncoder, 通过 http.ResponseEncoder() 配置,注⼊入到 http.Server() 中。
由于我们从http中接受并返回请求,因此我们应在
server/http.go 中进行修改。
// NewHTTPServer new an HTTP server.
func NewHTTPServer(c *conf.Server, todo *service.TodoService, logger log.Logger) *http.Server {
var opts = []http.ServerOption{
http.Middleware(
recovery.Recovery(),
),
}
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()))
}
srv := http.NewServer(opts...)
v1.RegisterTodoHTTPServer(srv, todo)
return srv
}

从他创建的NewServer可以看出来,他有一个默认的
enc:DefaultResponseEncoder
// DefaultResponseEncoder encodes the object to the HTTP response.
func DefaultResponseEncoder(w http.ResponseWriter, r *http.Request, v interface{}) error {
if v == nil {
return nil
}
if rd, ok := v.(Redirector); ok {
url, code := rd.Redirect()
http.Redirect(w, r, url, code)
return nil
}
codec, _ := CodecForRequest(r, "Accept")
data, err := codec.Marshal(v)
if err != nil {
return err
}
w.Header().Set("Content-Type", httputil.ContentType(codec.Name()))
_, err = w.Write(data)
if err != nil {
return err
}
return nil
}
此时我们使用http.ResponseEncoder(responseEncoder) 来替换
//可以看到他将ServerOption给转换
// ResponseEncoder with response encoder.
func ResponseEncoder(en EncodeResponseFunc) ServerOption {
return func(o *Server) {
o.enc = en
}
}
//仿写
// 自定义编码器
func responseEncoder(w http.ResponseWriter, r *http.Request, v interface{}) error {
if v == nil {
return nil
}
// 判断是不是重定向
if rd, ok := v.(kratoshttp.Redirector); ok {
url, code := rd.Redirect()
http.Redirect(w, r, url, code)
return nil
}
// 构造自定义的相应结构体
resp := &httpResponse{
Code: http.StatusOK,
Msg: "success",
Data: v,
}
codec, _ := kratoshttp.CodecForRequest(r, "Accept")
data, err := codec.Marshal(resp) // json.Marshal
if err != nil {
return err
}
// 设置响应头 Content-Type:application/json
w.Header().Set("Content-Type", "application/"+codec.Name())
_, err = w.Write(data)
return err
}