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