Skip to content

Commit

Permalink
feat: support form values in gateway (#2158)
Browse files Browse the repository at this point in the history
  • Loading branch information
kevwan committed Jul 16, 2022
1 parent 453fa30 commit b206dd2
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 20 deletions.
20 changes: 15 additions & 5 deletions gateway/requestparser.go
Expand Up @@ -7,12 +7,14 @@ import (

"github.com/fullstorydev/grpcurl"
"github.com/golang/protobuf/jsonpb"
"github.com/zeromicro/go-zero/rest/httpx"
"github.com/zeromicro/go-zero/rest/pathvar"
)

func buildJsonRequestParser(v interface{}, resolver jsonpb.AnyResolver) (grpcurl.RequestParser, error) {
func buildJsonRequestParser(m map[string]interface{}, resolver jsonpb.AnyResolver) (
grpcurl.RequestParser, error) {
var buf bytes.Buffer
if err := json.NewEncoder(&buf).Encode(v); err != nil {
if err := json.NewEncoder(&buf).Encode(m); err != nil {
return nil, err
}

Expand All @@ -21,20 +23,28 @@ func buildJsonRequestParser(v interface{}, resolver jsonpb.AnyResolver) (grpcurl

func newRequestParser(r *http.Request, resolver jsonpb.AnyResolver) (grpcurl.RequestParser, error) {
vars := pathvar.Vars(r)
if len(vars) == 0 {
params, err := httpx.GetFormValues(r)
if err != nil {
return nil, err
}

for k, v := range vars {
params[k] = v
}
if len(params) == 0 {
return grpcurl.NewJSONRequestParser(r.Body, resolver), nil
}

if r.ContentLength == 0 {
return buildJsonRequestParser(vars, resolver)
return buildJsonRequestParser(params, resolver)
}

m := make(map[string]interface{})
if err := json.NewDecoder(r.Body).Decode(&m); err != nil {
return nil, err
}

for k, v := range vars {
for k, v := range params {
m[k] = v
}

Expand Down
7 changes: 7 additions & 0 deletions gateway/requestparser_test.go
Expand Up @@ -46,3 +46,10 @@ func TestNewRequestParserWithVarsWithWrongBody(t *testing.T) {
assert.NotNil(t, err)
assert.Nil(t, parser)
}

func TestNewRequestParserWithForm(t *testing.T) {
req := httptest.NewRequest("GET", "/val?a=b", nil)
parser, err := newRequestParser(req, nil)
assert.Nil(t, err)
assert.NotNil(t, parser)
}
17 changes: 2 additions & 15 deletions rest/httpx/requests.go
Expand Up @@ -49,24 +49,11 @@ func ParseHeaders(r *http.Request, v interface{}) error {

// ParseForm parses the form request.
func ParseForm(r *http.Request, v interface{}) error {
if err := r.ParseForm(); err != nil {
params, err := GetFormValues(r)
if err != nil {
return err
}

if err := r.ParseMultipartForm(maxMemory); err != nil {
if err != http.ErrNotMultipart {
return err
}
}

params := make(map[string]interface{}, len(r.Form))
for name := range r.Form {
formValue := r.Form.Get(name)
if len(formValue) > 0 {
params[name] = formValue
}
}

return formUnmarshaler.Unmarshal(params, v)
}

Expand Down
23 changes: 23 additions & 0 deletions rest/httpx/util.go
Expand Up @@ -4,6 +4,29 @@ import "net/http"

const xForwardedFor = "X-Forwarded-For"

// GetFormValues returns the form values.
func GetFormValues(r *http.Request) (map[string]interface{}, error) {
if err := r.ParseForm(); err != nil {
return nil, err
}

if err := r.ParseMultipartForm(maxMemory); err != nil {
if err != http.ErrNotMultipart {
return nil, err
}
}

params := make(map[string]interface{}, len(r.Form))
for name := range r.Form {
formValue := r.Form.Get(name)
if len(formValue) > 0 {
params[name] = formValue
}
}

return params, nil
}

// GetRemoteAddr returns the peer address, supports X-Forward-For.
func GetRemoteAddr(r *http.Request) string {
v := r.Header.Get(xForwardedFor)
Expand Down

0 comments on commit b206dd2

Please sign in to comment.