Skip to content

Commit

Permalink
fix(net/ghttp): MakeBodyRepeatableRead takes not effective when cal…
Browse files Browse the repository at this point in the history
…led after `ParseForm` (#4143)
  • Loading branch information
cyjaysong authored Feb 11, 2025
1 parent 20b1987 commit 7d3b055
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 10 deletions.
20 changes: 10 additions & 10 deletions net/ghttp/ghttp_request_param.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,28 +268,28 @@ func (r *Request) parseForm() {
if r.ContentLength == 0 {
return
}

if contentType := r.Header.Get("Content-Type"); contentType != "" {
var (
err error
repeatableRead = true
)
if gstr.Contains(contentType, "multipart/") {
var isMultiPartRequest = gstr.Contains(contentType, "multipart/")
var isFormRequest = gstr.Contains(contentType, "form")
var err error

if !isMultiPartRequest {
// To avoid big memory consuming.
// The `multipart/` type form always contains binary data, which is not necessary read twice.
repeatableRead = false
r.MakeBodyRepeatableRead(true)
}
if isMultiPartRequest {
// multipart/form-data, multipart/mixed
if err = r.ParseMultipartForm(r.Server.config.FormParsingMemory); err != nil {
panic(gerror.WrapCode(gcode.CodeInvalidRequest, err, "r.ParseMultipartForm failed"))
}
} else if gstr.Contains(contentType, "form") {
} else if isFormRequest {
// application/x-www-form-urlencoded
if err = r.Request.ParseForm(); err != nil {
panic(gerror.WrapCode(gcode.CodeInvalidRequest, err, "r.Request.ParseForm failed"))
}
}
if repeatableRead {
r.MakeBodyRepeatableRead(true)
}
if len(r.PostForm) > 0 {
// Parse the form data using united parsing way.
params := ""
Expand Down
36 changes: 36 additions & 0 deletions net/ghttp/ghttp_z_unit_feature_request_struct_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,42 @@ func Test_Params_ParseForm(t *testing.T) {
})
}

// https://github.com/gogf/gf/pull/4143
func Test_Params_ParseForm_FixMakeBodyRepeatableRead(t *testing.T) {
type User struct {
Id int
Name string
}
s := g.Server(guid.S())
s.BindHandler("/parse-form", func(r *ghttp.Request) {
var user *User
if err := r.ParseForm(&user); err != nil {
r.Response.WriteExit(err)
}
hasBody := len(r.GetBody()) > 0
r.Response.WriteExit(hasBody)
})
s.SetDumpRouterMap(false)
s.Start()
defer s.Shutdown()

time.Sleep(100 * time.Millisecond)
gtest.C(t, func(t *gtest.T) {
c := g.Client()
c.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", s.GetListenedPort()))
t.Assert(c.GetContent(ctx, "/parse-form"), `false`)
t.Assert(c.GetContent(ctx, "/parse-form", g.Map{
"id": 1,
"name": "john",
}), false)
t.Assert(c.PostContent(ctx, "/parse-form"), `false`)
t.Assert(c.PostContent(ctx, "/parse-form", g.Map{
"id": 1,
"name": "john",
}), true)
})
}

func Test_Params_ComplexJsonStruct(t *testing.T) {
type ItemEnv struct {
Type string
Expand Down

0 comments on commit 7d3b055

Please sign in to comment.