package http import ( "net/http" "strings" "github.com/go-kratos/kratos/v2/encoding" "github.com/go-kratos/kratos/v2/errors" "github.com/go-kratos/kratos/v2/encoding/json" _ "github.com/go-kratos/kratos/v2/encoding/proto" ) // decodeRequest decodes the request body to object. //func DecodeRequest(req *http.Request, v interface{}) error { // method := strings.ToUpper(req.Method) // if method == "POST" || method == "PUT" || method == "DELETE" { // if _, ok := v.(*emptypb.Empty); ok { // return binding.BindForm(req, v) // } // subtype := contentSubtype(req.Header.Get(ContentTypeHeader)) // if codec := encoding.GetCodec(subtype); codec != nil { // data, err := ioutil.ReadAll(req.Body) // if err != nil { // return err // } // return codec.Unmarshal(data, v) // } // } // return binding.BindForm(req, v) //} func ErrHandle(w http.ResponseWriter, r *http.Request, err error) { se, ok := errors.FromError(err) if !ok { se = &errors.StatusError{ Code: 10500, Message: err.Error(), } } if se.Code == -1 { return } codec := codecForRequest(r) w.Header().Set(ContentTypeHeader, contentType(codec.Name())) if se.Code == 0 { w.WriteHeader(200) } else if se.Code >= 302 && se.Code <= 303 { w.WriteHeader(int(se.Code)) http.Redirect(w, r, se.Message, int(se.Code)) return } else { if se.Code < 10000 { se.Code = 10000 + se.Code } if se.Code < 10100 && se.Message == "" { se.Message = "系统错误" } w.WriteHeader(400) } data, _ := codec.Marshal(se) _, _ = w.Write(data) } const baseContentType = "application" var ( acceptHeader = http.CanonicalHeaderKey("Accept") ContentTypeHeader = http.CanonicalHeaderKey("Content-Type") ) func contentType(subtype string) string { return strings.Join([]string{baseContentType, subtype}, "/") } // codecForRequest get encoding.Codec via http.Request func codecForRequest(r *http.Request) encoding.Codec { var codec encoding.Codec for _, accept := range r.Header[acceptHeader] { codeName := contentSubtype(accept) if codeName == "json" { codec = encoding.GetCodec(json.Name) break } if codec = encoding.GetCodec(codeName); codec != nil { break } } if codec == nil { codec = encoding.GetCodec(json.Name) } return codec } func contentSubtype(contentType string) string { if contentType == baseContentType { return "" } if !strings.HasPrefix(contentType, baseContentType) { return "" } switch contentType[len(baseContentType)] { case '/', ';': if i := strings.Index(contentType, ";"); i != -1 { return contentType[len(baseContentType)+1 : i] } return contentType[len(baseContentType)+1:] default: return "" } }