go-zero
go-zero copied to clipboard
Gateway how to add data head for response body?
Add:
{"code":0,"data":{ ANY }
for success response body.
Add:
{"code":ERRCODE,"message":"error message"}
for fail response body.
httpx.SetErrorHandlerCtx supports fail response, but httpx.SetOkHandler does not work.
The following approach works with middleware, but is inelegant:
server.Use(wrapResponse)
type responseWriter struct {
http.ResponseWriter
statusCode int
body bytes.Buffer
}
func (rw *responseWriter) WriteHeader(statusCode int) {
rw.statusCode = statusCode
rw.ResponseWriter.WriteHeader(statusCode)
}
func (rw *responseWriter) Write(p []byte) (int, error) {
return rw.body.Write(p)
}
func (rw *responseWriter) Body() []byte {
return rw.body.Bytes()
}
// 对响应加上“"code":0,"data":{}”,
// 对于已经包含了“code”的不做任何处理(原因是 grpcErrorHandler 才能处理好)
func wrapResponse(next http.HandlerFunc) http.HandlerFunc {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// 记录原始响应 writer
rw := &responseWriter{
ResponseWriter: w,
statusCode: http.StatusOK,
}
// 执行下一个中间件或处理函数
next.ServeHTTP(rw, r)
// 检查响应状态码
if rw.statusCode != http.StatusOK {
return
}
// 获取原始响应数据
var resp map[string]interface{}
err := json.Unmarshal(rw.Body(), &resp)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// 检查响应是否已经包含 code
if _, ok := resp["code"]; ok {
// 如果响应已经包含 code,则直接写回原始响应正文
w.Header().Set("Content-Type", "application/json")
w.Write(rw.Body())
return
}
// 包装响应数据
wrappedResp := map[string]interface{}{
"code": 0,
"data": resp,
}
// 将包装后的响应数据写回 response body
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(wrappedResp)
})
}
type MyResponse struct {
Code int `json:"code"`
Message string `json:"message"`
Data interface{} `json:"data,omitempty"`
}
@kevwan @gongluck @kesonan Thanks.
Reference test cases, maybe you can use
httpx.OkJson(w, wrappedResp)
replace
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(wrappedResp)
Bot detected the issue body's language is not English, translate it automatically. 👯👭🏻🧑🤝🧑👫🧑🏿🤝🧑🏻👩🏾🤝👨🏿👬🏿
Reference test cases, maybe you can use
httpx.OkJson(w, wrappedResp)
replace
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(wrappedResp)
httpx.OkJson(w, wrappedResp)
Thanks. I hope to achieve the goal without using "server.Use(wrapResponse)", which is a non-elegant way to implement it.
@eyjian problem solved?
@eyjian problem solved?
Thank you, it's a temporary solution, but it's not elegant and not a satisfactory way. In addition, I hope that the gateway will not be unable to start because a certain service is not started. This is unreasonable. Just because a service cannot start, the gateway cannot start. This is a big problem.
The solution is as follows: https://github.com/eyjian/mooon-gateway/blob/main/main.go