github.com/bytedance/go-tagexpr@v2.7.5-0.20210114074101-de5b8743ad85+incompatible/binding/body.go (about) 1 package binding 2 3 import ( 4 "bytes" 5 jsonpkg "encoding/json" 6 "errors" 7 "io" 8 "net/http" 9 "strings" 10 11 "github.com/gogo/protobuf/proto" 12 ) 13 14 func getBodyCodec(req Request) codec { 15 ct := req.GetContentType() 16 idx := strings.Index(ct, ";") 17 if idx != -1 { 18 ct = strings.TrimRight(ct[:idx], " ") 19 } 20 switch ct { 21 case "application/json": 22 return bodyJSON 23 case "application/x-protobuf": 24 return bodyProtobuf 25 case "application/x-www-form-urlencoded", "multipart/form-data": 26 return bodyForm 27 default: 28 return bodyUnsupport 29 } 30 } 31 32 // Body body copy 33 type Body struct { 34 *bytes.Buffer 35 bodyBytes []byte 36 } 37 38 // Close close. 39 func (Body) Close() error { return nil } 40 41 // Reset zero offset. 42 func (b *Body) Reset() { 43 b.Buffer = bytes.NewBuffer(b.bodyBytes) 44 } 45 46 // Bytes returns all of the body bytes. 47 func (b *Body) Bytes() []byte { 48 return b.bodyBytes 49 } 50 51 // Len returns all of the body length. 52 func (b *Body) Len() int { 53 return len(b.bodyBytes) 54 } 55 56 // GetBody get the body from http.Request 57 func GetBody(r *http.Request) (*Body, error) { 58 switch body := r.Body.(type) { 59 case *Body: 60 body.Reset() 61 return body, nil 62 default: 63 var buf bytes.Buffer 64 _, err := io.Copy(&buf, r.Body) 65 r.Body.Close() 66 if err != nil { 67 return nil, err 68 } 69 _body := &Body{ 70 Buffer: &buf, 71 bodyBytes: buf.Bytes(), 72 } 73 r.Body = _body 74 return _body, nil 75 } 76 } 77 78 func bindJSON(pointer interface{}, bodyBytes []byte) error { 79 if jsonUnmarshalFunc != nil { 80 return jsonUnmarshalFunc(bodyBytes, pointer) 81 } 82 return jsonpkg.Unmarshal(bodyBytes, pointer) 83 } 84 85 func bindProtobuf(pointer interface{}, bodyBytes []byte) error { 86 msg, ok := pointer.(proto.Message) 87 if !ok { 88 return errors.New("protobuf content type is not supported") 89 } 90 return proto.Unmarshal(bodyBytes, msg) 91 }