github.com/hduhelp/go-zero@v1.4.3/gateway/internal/requestparser.go (about)

     1  package internal
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"io"
     7  	"net/http"
     8  
     9  	"github.com/fullstorydev/grpcurl"
    10  	"github.com/golang/protobuf/jsonpb"
    11  	"github.com/hduhelp/go-zero/rest/httpx"
    12  	"github.com/hduhelp/go-zero/rest/pathvar"
    13  )
    14  
    15  // NewRequestParser creates a new request parser from the given http.Request and resolver.
    16  func NewRequestParser(r *http.Request, resolver jsonpb.AnyResolver) (grpcurl.RequestParser, error) {
    17  	vars := pathvar.Vars(r)
    18  	params, err := httpx.GetFormValues(r)
    19  	if err != nil {
    20  		return nil, err
    21  	}
    22  
    23  	for k, v := range vars {
    24  		params[k] = v
    25  	}
    26  
    27  	body, ok := getBody(r)
    28  	if !ok {
    29  		return buildJsonRequestParser(params, resolver)
    30  	}
    31  
    32  	if len(params) == 0 {
    33  		return grpcurl.NewJSONRequestParser(body, resolver), nil
    34  	}
    35  
    36  	m := make(map[string]interface{})
    37  	if err := json.NewDecoder(body).Decode(&m); err != nil {
    38  		return nil, err
    39  	}
    40  
    41  	for k, v := range params {
    42  		m[k] = v
    43  	}
    44  
    45  	return buildJsonRequestParser(m, resolver)
    46  }
    47  
    48  func buildJsonRequestParser(m map[string]interface{}, resolver jsonpb.AnyResolver) (
    49  	grpcurl.RequestParser, error) {
    50  	var buf bytes.Buffer
    51  	if err := json.NewEncoder(&buf).Encode(m); err != nil {
    52  		return nil, err
    53  	}
    54  
    55  	return grpcurl.NewJSONRequestParser(&buf, resolver), nil
    56  }
    57  
    58  func getBody(r *http.Request) (io.Reader, bool) {
    59  	if r.Body == nil {
    60  		return nil, false
    61  	}
    62  
    63  	if r.ContentLength == 0 {
    64  		return nil, false
    65  	}
    66  
    67  	if r.ContentLength > 0 {
    68  		return r.Body, true
    69  	}
    70  
    71  	var buf bytes.Buffer
    72  	if _, err := io.Copy(&buf, r.Body); err != nil {
    73  		return nil, false
    74  	}
    75  
    76  	if buf.Len() > 0 {
    77  		return &buf, true
    78  	}
    79  
    80  	return nil, false
    81  }