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  }