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  }