Files
lone-services/bff/internal/response/middleware.go
T
gjs 6c20427b0a
CI / changes (push) Successful in 2s
CI / docker-bff (push) Successful in 3m7s
CI / docker-product (push) Has been skipped
CI / docker-admin (push) Successful in 3m26s
bff config to nacos
2026-08-13 16:27:18 +08:00

123 lines
2.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package response
import (
"bytes"
"encoding/json"
"net/http"
"strings"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
type bodyWriter struct {
http.ResponseWriter
status int
buf bytes.Buffer
}
type responseData struct {
Code int32 `json:"code"`
Data any `json:"data"`
Msg string `json:"msg"`
}
func (w *bodyWriter) WriteHeader(statusCode int) {
w.status = statusCode
}
func (w *bodyWriter) Write(b []byte) (int, error) {
return w.buf.Write(b)
}
func Wrap(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
bw := &bodyWriter{ResponseWriter: w, status: http.StatusOK}
next(bw, r)
ctrl := BaseController{}
if bw.status != http.StatusOK {
ctrl.Error(w, mapHTTPError(bw.status, bw.buf.String()))
return
}
raw := bytes.TrimSpace(bw.buf.Bytes())
var data responseData
if len(raw) > 0 {
if err := json.Unmarshal(raw, &data); err != nil {
ctrl.Fail(w)
return
}
}
ctrl.OutPut(w, data.Code, unwrapJSONData(data.Data), data.Msg)
}
}
// unwrapJSONData 将 RPC Response.dataproto string)里的 JSON 文本还原为对象/数组/数字。
func unwrapJSONData(v any) any {
s, ok := v.(string)
if !ok {
return v
}
s = strings.TrimSpace(s)
if s == "" {
return nil
}
var parsed any
if err := json.Unmarshal([]byte(s), &parsed); err != nil {
return v
}
return parsed
}
func mapHTTPError(httpStatus int, body string) Error {
msg := strings.TrimSpace(body)
msg = strings.TrimPrefix(msg, "rpc error: ")
if i := strings.Index(msg, "desc = "); i >= 0 {
msg = strings.TrimSpace(msg[i+len("desc = "):])
}
if msg == "" {
msg = Fail.GetMsg()
}
switch httpStatus {
case http.StatusBadRequest:
return Define(ErrorMissingParams, msg)
case http.StatusUnauthorized:
return Define(ErrorNoLogin, msg)
case http.StatusForbidden:
return Define(ErrorAuthority, msg)
case http.StatusNotFound:
return Define(ErrorDataNotExist, msg)
default:
return Define(Fail, msg)
}
}
func FromGRPC(err error) Error {
if err == nil {
return OK
}
st, ok := status.FromError(err)
if !ok {
return Define(Fail, err.Error())
}
msg := st.Message()
if msg == "" {
msg = st.Code().String()
}
switch st.Code() {
case codes.InvalidArgument:
return Define(ErrorMissingParams, msg)
case codes.Unauthenticated:
return Define(ErrorNoLogin, msg)
case codes.PermissionDenied:
return Define(ErrorAuthority, msg)
case codes.NotFound:
return Define(ErrorDataNotExist, msg)
case codes.AlreadyExists:
return Define(ErrorDataIsExist, msg)
default:
return Define(Fail, msg)
}
}