-
-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Question] How to return a custom response json? #3268
Labels
question
Further information is requested
Comments
package server
import (
v1 "code_msg_data/api/helloworld/v1"
"code_msg_data/internal/conf"
"code_msg_data/internal/service"
sj "encoding/json"
nt "net/http"
"strings"
"github.com/go-kratos/kratos/v2/encoding"
"github.com/go-kratos/kratos/v2/encoding/json"
"github.com/go-kratos/kratos/v2/errors"
"github.com/go-kratos/kratos/v2/log"
"github.com/go-kratos/kratos/v2/middleware/recovery"
"github.com/go-kratos/kratos/v2/transport/http"
)
// 最终效果
// $ curl http://localhost:8000/helloworld/kvii
// {"code":0,"message":"success","data":{"message":"Hello kvii"}}
// $ curl http://localhost:8000/helloworld/err
// {"code":404,"message":"user not found"}
// NewHTTPServer new an HTTP server.
func NewHTTPServer(c *conf.Server, greeter *service.GreeterService, logger log.Logger) *http.Server {
var opts = []http.ServerOption{
http.Middleware(
recovery.Recovery(),
),
http.ErrorEncoder(DefaultErrorEncoder), // <- 关键代码
http.ResponseEncoder(DefaultResponseEncoder), // <- 关键代码
}
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.RegisterGreeterHTTPServer(srv, greeter)
return srv
}
// DefaultResponseEncoder copy from http.DefaultResponseEncoder
func DefaultResponseEncoder(w http.ResponseWriter, r *http.Request, v interface{}) error {
if v == nil {
return nil
}
if rd, ok := v.(http.Redirector); ok {
url, code := rd.Redirect()
nt.Redirect(w, r, url, code)
return nil
}
codec := encoding.GetCodec(json.Name) // ignore Accept Header
data, err := codec.Marshal(v)
if err != nil {
return err
}
bs, _ := sj.Marshal(NewResponse(data))
w.Header().Set("Content-Type", ContentType(codec.Name()))
_, err = w.Write(bs)
if err != nil {
return err
}
return nil
}
// DefaultErrorEncoder copy from http.DefaultErrorEncoder.
func DefaultErrorEncoder(w http.ResponseWriter, r *http.Request, err error) {
se := FromError(errors.FromError(err)) // change error to BaseResponse
codec := encoding.GetCodec(json.Name) // ignore Accept header
body, err := codec.Marshal(se)
if err != nil {
w.WriteHeader(nt.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", ContentType(codec.Name()))
// w.WriteHeader(int(se.Code)) // ignore http status code
_, _ = w.Write(body)
}
const (
baseContentType = "application"
)
// ContentType returns the content-type with base prefix.
func ContentType(subtype string) string {
return strings.Join([]string{baseContentType, subtype}, "/")
}
func NewResponse(data []byte) BaseResponse {
return BaseResponse{
Code: 0,
Message: "success",
Data: sj.RawMessage(data),
}
}
func FromError(e *errors.Error) *BaseResponse {
if e == nil {
return nil
}
return &BaseResponse{
Code: e.Code,
Message: e.Message,
}
}
type BaseResponse struct {
Code int32 `json:"code"`
Message string `json:"message"`
Data sj.RawMessage `json:"data,omitempty"`
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
How to return a custom response json?
The text was updated successfully, but these errors were encountered: