package http import ( "io/ioutil" "net/http" "github.com/go-kratos/kratos/v2/encoding" "github.com/go-kratos/kratos/v2/errors" "github.com/go-kratos/kratos/v2/internal/httputil" "github.com/go-kratos/kratos/v2/transport/http/binding" ) // SupportPackageIsVersion1 These constants should not be referenced from any other code. const SupportPackageIsVersion1 = true // DecodeRequestFunc is decode request func. type DecodeRequestFunc func(*http.Request, interface{}) error // EncodeResponseFunc is encode response func. type EncodeResponseFunc func(http.ResponseWriter, *http.Request, interface{}) error // EncodeErrorFunc is encode error func. type EncodeErrorFunc func(http.ResponseWriter, *http.Request, error) // DefaultRequestDecoder decodes the request body to object. func DefaultRequestDecoder(r *http.Request, v interface{}) error { if codec, ok := CodecForRequest(r, "Content-Type"); ok { data, err := ioutil.ReadAll(r.Body) if err != nil { return errors.BadRequest("CODEC", err.Error()) } if err := codec.Unmarshal(data, v); err != nil { return errors.BadRequest("CODEC", err.Error()) } return nil } if err := binding.BindForm(r, v); err != nil { return errors.BadRequest("CODEC", err.Error()) } return nil } // DefaultResponseEncoder encodes the object to the HTTP response. func DefaultResponseEncoder(w http.ResponseWriter, r *http.Request, v interface{}) error { codec, _ := CodecForRequest(r, "Accept") data, err := codec.Marshal(v) if err != nil { return err } w.Header().Set("Content-Type", httputil.ContentType(codec.Name())) if sc, ok := v.(interface { StatusCode() int }); ok { w.WriteHeader(sc.StatusCode()) } _, _ = w.Write(data) return nil } // DefaultErrorEncoder encodes the error to the HTTP response. func DefaultErrorEncoder(w http.ResponseWriter, r *http.Request, se error) { codec, _ := CodecForRequest(r, "Accept") body, err := codec.Marshal(se) if err != nil { w.WriteHeader(http.StatusInternalServerError) return } w.Header().Set("Content-Type", httputil.ContentType(codec.Name())) if sc, ok := se.(interface { StatusCode() int }); ok { w.WriteHeader(sc.StatusCode()) } else { w.WriteHeader(http.StatusInternalServerError) } w.Write(body) } // CodecForRequest get encoding.Codec via http.Request func CodecForRequest(r *http.Request, name string) (encoding.Codec, bool) { for _, accept := range r.Header[name] { codec := encoding.GetCodec(httputil.ContentSubtype(accept)) if codec != nil { return codec, true } } return encoding.GetCodec("json"), false }