From 13042dfd4e3dfd6679c2996d796bd96890fda0d7 Mon Sep 17 00:00:00 2001
From: thinkerou <thinkerou@gmail.com>
Date: Tue, 24 Oct 2017 17:44:09 +0800
Subject: [PATCH 1/8] support default value for form

---
 binding/form_mapping.go | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/binding/form_mapping.go b/binding/form_mapping.go
index c968dc08d7..e824d39ced 100644
--- a/binding/form_mapping.go
+++ b/binding/form_mapping.go
@@ -8,6 +8,7 @@ import (
 	"errors"
 	"reflect"
 	"strconv"
+	"strings"
 	"time"
 )
 
@@ -23,6 +24,15 @@ func mapForm(ptr interface{}, form map[string][]string) error {
 
 		structFieldKind := structField.Kind()
 		inputFieldName := typeField.Tag.Get("form")
+		inputFieldNameList := strings.Split(inputFieldName, ",")
+		inputFieldName = inputFieldNameList[0]
+		var defaultValue interface{}
+		if len(inputFieldNameList) > 1 {
+			defaultList := strings.Split(inputFieldNameList[1], "=")
+			if len(defaultList) == 2 && defaultList[0] == "default" {
+				defaultValue = defaultList[1]
+			}
+		}
 		if inputFieldName == "" {
 			inputFieldName = typeField.Name
 
@@ -38,8 +48,13 @@ func mapForm(ptr interface{}, form map[string][]string) error {
 			}
 		}
 		inputValue, exists := form[inputFieldName]
+
 		if !exists {
-			continue
+			if defaultValue.(string) == "" {
+				continue
+			}
+			inputValue = make([]string, 1)
+			inputValue[0] = defaultValue.(string)
 		}
 
 		numElems := len(inputValue)

From b4d1b55cc2efceeb8c68857735395119ac7a4dd2 Mon Sep 17 00:00:00 2001
From: thinkerou <thinkerou@gmail.com>
Date: Tue, 24 Oct 2017 21:38:42 +0800
Subject: [PATCH 2/8] fix bug for nil interface

---
 binding/form_mapping.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/binding/form_mapping.go b/binding/form_mapping.go
index e824d39ced..3ced55be02 100644
--- a/binding/form_mapping.go
+++ b/binding/form_mapping.go
@@ -50,7 +50,7 @@ func mapForm(ptr interface{}, form map[string][]string) error {
 		inputValue, exists := form[inputFieldName]
 
 		if !exists {
-			if defaultValue.(string) == "" {
+			if defaultValue == nil {
 				continue
 			}
 			inputValue = make([]string, 1)

From 4654192b83702ab375234caac222107da0a35c02 Mon Sep 17 00:00:00 2001
From: thinkerou <thinkerou@gmail.com>
Date: Tue, 24 Oct 2017 23:07:03 +0800
Subject: [PATCH 3/8] use SplitN and optimization code

---
 binding/form_mapping.go | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/binding/form_mapping.go b/binding/form_mapping.go
index 3ced55be02..a042ceef68 100644
--- a/binding/form_mapping.go
+++ b/binding/form_mapping.go
@@ -26,10 +26,10 @@ func mapForm(ptr interface{}, form map[string][]string) error {
 		inputFieldName := typeField.Tag.Get("form")
 		inputFieldNameList := strings.Split(inputFieldName, ",")
 		inputFieldName = inputFieldNameList[0]
-		var defaultValue interface{}
+		var defaultValue string
 		if len(inputFieldNameList) > 1 {
-			defaultList := strings.Split(inputFieldNameList[1], "=")
-			if len(defaultList) == 2 && defaultList[0] == "default" {
+			defaultList := strings.SplitN(inputFieldNameList[1], "=", 2)
+			if defaultList[0] == "default" {
 				defaultValue = defaultList[1]
 			}
 		}
@@ -50,11 +50,11 @@ func mapForm(ptr interface{}, form map[string][]string) error {
 		inputValue, exists := form[inputFieldName]
 
 		if !exists {
-			if defaultValue == nil {
+			if defaultValue == "" {
 				continue
 			}
 			inputValue = make([]string, 1)
-			inputValue[0] = defaultValue.(string)
+			inputValue[0] = defaultValue
 		}
 
 		numElems := len(inputValue)

From e9773bfdd0e02fcd1f2aa42e98b8bf62a2dd4730 Mon Sep 17 00:00:00 2001
From: thinkerou <thinkerou@gmail.com>
Date: Sun, 12 Nov 2017 17:19:31 +0800
Subject: [PATCH 4/8] add test case

---
 binding/binding_test.go | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/binding/binding_test.go b/binding/binding_test.go
index 5575e16610..a88d71465d 100644
--- a/binding/binding_test.go
+++ b/binding/binding_test.go
@@ -25,6 +25,11 @@ type FooBarStruct struct {
 	Bar string `msgpack:"bar" json:"bar" form:"bar" xml:"bar" binding:"required"`
 }
 
+type FooDefaultBarStruct struct {
+	FooStruct
+	Bar string `msgpack:"bar" json:"bar,default=hello" form:"bar" xml:"bar" binding:"required"`
+}
+
 func TestBindingDefault(t *testing.T) {
 	assert.Equal(t, Default("GET", ""), Form)
 	assert.Equal(t, Default("GET", MIMEJSON), Form)
@@ -92,6 +97,12 @@ func createFormPostRequest() *http.Request {
 	return req
 }
 
+func createDefaultFormPostRequest() *http.Request {
+	req, _ := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", bytes.NewBufferString("foo=bar"))
+	req.Header.Set("Content-Type", MIMEPOSTForm)
+	return req
+}
+
 func createFormMultipartRequest() *http.Request {
 	boundary := "--testboundary"
 	body := new(bytes.Buffer)
@@ -115,6 +126,15 @@ func TestBindingFormPost(t *testing.T) {
 	assert.Equal(t, obj.Bar, "foo")
 }
 
+func TestBindingDefaultValueFormPost(t *testing.T) {
+	req := createDefaultFormPostRequest()
+	var obj FooDefaultBarStruct
+	FormPost.Bind(req, &obj)
+
+	assert.Equal(t, obj.Foo, "bar")
+	assert.Equal(t, obj.Bar, "hello")
+}
+
 func TestBindingFormMultipart(t *testing.T) {
 	req := createFormMultipartRequest()
 	var obj FooBarStruct

From 8027a23db9bf191406f9e4ab03c0369cbd6b83d2 Mon Sep 17 00:00:00 2001
From: thinkerou <thinkerou@gmail.com>
Date: Sun, 12 Nov 2017 21:30:55 +0800
Subject: [PATCH 5/8] add test cases for form(own default value)

---
 binding/binding_test.go | 34 +++++++++++++++++++++++++++++++++-
 1 file changed, 33 insertions(+), 1 deletion(-)

diff --git a/binding/binding_test.go b/binding/binding_test.go
index a88d71465d..5e0cee5e06 100644
--- a/binding/binding_test.go
+++ b/binding/binding_test.go
@@ -27,7 +27,7 @@ type FooBarStruct struct {
 
 type FooDefaultBarStruct struct {
 	FooStruct
-	Bar string `msgpack:"bar" json:"bar,default=hello" form:"bar" xml:"bar" binding:"required"`
+	Bar string `msgpack:"bar" json:"bar" form:"bar,default=hello" xml:"bar" binding:"required"`
 }
 
 func TestBindingDefault(t *testing.T) {
@@ -72,6 +72,18 @@ func TestBindingForm2(t *testing.T) {
 		"", "")
 }
 
+func TestBindingFormDefaultValue(t *testing.T) {
+	testFormBindingDefaultValue(t, "POST",
+		"/", "/",
+		"foo=bar", "bar2=foo")
+}
+
+func TestBindingFormDefaultValue2(t *testing.T) {
+	testFormBindingDefaultValue(t, "GET",
+		"/?foo=bar", "/?bar2=foo",
+		"", "")
+}
+
 func TestBindingQuery(t *testing.T) {
 	testQueryBinding(t, "POST",
 		"/?foo=bar&bar=foo", "/",
@@ -236,6 +248,26 @@ func testFormBinding(t *testing.T, method, path, badPath, body, badBody string)
 	assert.Error(t, err)
 }
 
+func testFormBindingDefaultValue(t *testing.T, method, path, badPath, body, badBody string) {
+	b := Form
+	assert.Equal(t, b.Name(), "form")
+
+	obj := FooDefaultBarStruct{}
+	req := requestWithBody(method, path, body)
+	if method == "POST" {
+		req.Header.Add("Content-Type", MIMEPOSTForm)
+	}
+	err := b.Bind(req, &obj)
+	assert.NoError(t, err)
+	assert.Equal(t, obj.Foo, "bar")
+	assert.Equal(t, obj.Bar, "hello")
+
+	obj = FooDefaultBarStruct{}
+	req = requestWithBody(method, badPath, badBody)
+	err = JSON.Bind(req, &obj)
+	assert.Error(t, err)
+}
+
 func testQueryBinding(t *testing.T, method, path, badPath, body, badBody string) {
 	b := Query
 	assert.Equal(t, b.Name(), "query")

From bcd046b40fc53cbb74ff122aa447ae26bd596adf Mon Sep 17 00:00:00 2001
From: tianou <tianou@kuaishou.com>
Date: Tue, 17 Apr 2018 13:05:43 +0800
Subject: [PATCH 6/8] fix invalid code

---
 binding/binding_test.go | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/binding/binding_test.go b/binding/binding_test.go
index 956e3698d6..ba64c26c1b 100644
--- a/binding/binding_test.go
+++ b/binding/binding_test.go
@@ -615,12 +615,12 @@ func testFormBindingDefaultValue(t *testing.T, method, path, badPath, body, badB
 	assert.Equal(t, b.Name(), "form")
 
 	obj := FooDefaultBarStruct{}
-    req := requestWithBody(method, path, body)
+	req := requestWithBody(method, path, body)
 	if method == "POST" {
 		req.Header.Add("Content-Type", MIMEPOSTForm)
 	}
 	err := b.Bind(req, &obj)
-    assert.NoError(t, err)
+	assert.NoError(t, err)
 	assert.Equal(t, obj.Foo, "bar")
 	assert.Equal(t, obj.Bar, "hello")
 
@@ -670,11 +670,6 @@ func testFormBindingForTime(t *testing.T, method, path, badPath, body, badBody s
 		req.Header.Add("Content-Type", MIMEPOSTForm)
 	}
 	err := b.Bind(req, &obj)
-	assert.NoError(t, err)
-	assert.Equal(t, obj.Foo, "bar")
-	assert.Equal(t, obj.Bar, "hello")
-
-	obj = FooDefaultBarStruct{}
 
 	assert.NoError(t, err)
 	assert.Equal(t, obj.TimeFoo.Unix(), int64(1510675200))

From 5a1c743045f4f01e2e4dd650ec628e21d075f9b3 Mon Sep 17 00:00:00 2001
From: thinkerou <thinkerou@gmail.com>
Date: Tue, 17 Apr 2018 13:15:38 +0800
Subject: [PATCH 7/8] fix code indent

---
 binding/binding_test.go | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/binding/binding_test.go b/binding/binding_test.go
index ba64c26c1b..7dc57ed021 100644
--- a/binding/binding_test.go
+++ b/binding/binding_test.go
@@ -426,8 +426,8 @@ func createFormPostRequest() *http.Request {
 
 func createDefaultFormPostRequest() *http.Request {
 	req, _ := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", bytes.NewBufferString("foo=bar"))
-    req.Header.Set("Content-Type", MIMEPOSTForm)
-    return req
+	req.Header.Set("Content-Type", MIMEPOSTForm)
+	return req
 }
 
 func createFormPostRequestFail() *http.Request {

From 0d2480e10fb1e0798b0791f631f2c49083fe60fb Mon Sep 17 00:00:00 2001
From: thinkerou <thinkerou@gmail.com>
Date: Fri, 20 Apr 2018 10:36:12 +0800
Subject: [PATCH 8/8] assert order

---
 binding/binding_test.go | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/binding/binding_test.go b/binding/binding_test.go
index 0938dda27e..ac82641781 100644
--- a/binding/binding_test.go
+++ b/binding/binding_test.go
@@ -478,8 +478,8 @@ func TestBindingDefaultValueFormPost(t *testing.T) {
 	var obj FooDefaultBarStruct
 	FormPost.Bind(req, &obj)
 
-	assert.Equal(t, obj.Foo, "bar")
-	assert.Equal(t, obj.Bar, "hello")
+	assert.Equal(t, "bar", obj.Foo)
+	assert.Equal(t, "hello", obj.Bar)
 }
 
 func TestBindingFormPostFail(t *testing.T) {
@@ -612,7 +612,7 @@ func testFormBinding(t *testing.T, method, path, badPath, body, badBody string)
 
 func testFormBindingDefaultValue(t *testing.T, method, path, badPath, body, badBody string) {
 	b := Form
-	assert.Equal(t, b.Name(), "form")
+	assert.Equal(t, "form", b.Name())
 
 	obj := FooDefaultBarStruct{}
 	req := requestWithBody(method, path, body)
@@ -621,8 +621,8 @@ func testFormBindingDefaultValue(t *testing.T, method, path, badPath, body, badB
 	}
 	err := b.Bind(req, &obj)
 	assert.NoError(t, err)
-	assert.Equal(t, obj.Foo, "bar")
-	assert.Equal(t, obj.Bar, "hello")
+	assert.Equal(t, "bar", obj.Foo)
+	assert.Equal(t, "hello", obj.Bar)
 
 	obj = FooDefaultBarStruct{}
 	req = requestWithBody(method, badPath, badBody)