go-kratos(2)

自定义响应

目标编码

我们需要额外返回状态码和信息。
我们可以覆盖默认的 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
}

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容