fix empty value error

Here is the code that can report an error
```go
package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"io"
	"net/http"
	"os"
	"time"
)

type header struct {
	Duration   time.Duration `header:"duration"`
	CreateTime time.Time     `header:"createTime" time_format:"unix"`
}

func needFix1() {
	g := gin.Default()
	g.GET("/", func(c *gin.Context) {
		h := header{}
		err := c.ShouldBindHeader(&h)
		if err != nil {
			c.JSON(500, fmt.Sprintf("fail:%s\n", err))
			return
		}

		c.JSON(200, h)
	})

	g.Run(":8081")
}

func needFix2() {
	g := gin.Default()
	g.GET("/", func(c *gin.Context) {
		h := header{}
		err := c.ShouldBindHeader(&h)
		if err != nil {
			c.JSON(500, fmt.Sprintf("fail:%s\n", err))
			return
		}

		c.JSON(200, h)
	})

	g.Run(":8082")
}

func sendNeedFix1() {
	// send to needFix1
	sendBadData("http://127.0.0.1:8081", "duration")
}

func sendNeedFix2() {
	// send to needFix2
	sendBadData("http://127.0.0.1:8082", "createTime")
}

func sendBadData(url, key string) {
	req, err := http.NewRequest("GET", "http://127.0.0.1:8081", nil)
	if err != nil {
		fmt.Printf("err:%s\n", err)
		return
	}

	// Only the key and no value can cause an error
	req.Header.Add(key, "")
	rsp, err := http.DefaultClient.Do(req)
	if err != nil {
		return
	}
	io.Copy(os.Stdout, rsp.Body)
	rsp.Body.Close()
}

func main() {
	go needFix1()
	go needFix2()

	time.Sleep(time.Second / 1000 * 200) // 200ms
	sendNeedFix1()
	sendNeedFix2()
}

```
This commit is contained in:
guonaihong 2019-12-06 15:49:43 +08:00
parent 7c21e04f62
commit 7e9f808e02
2 changed files with 36 additions and 5 deletions

View File

@ -1271,3 +1271,30 @@ func requestWithBody(method, path, body string) (req *http.Request) {
req, _ = http.NewRequest(method, path, bytes.NewBufferString(body))
return
}
type bindTestData struct {
need interface{}
got interface{}
in map[string][]string
}
func Test_Binding_BaseType(t *testing.T) {
type needFixDurationEmpty struct {
Duration time.Duration `form:"duration"`
}
type needFixUnixNanoEmpty struct {
CreateTime time.Time `form:"createTime" time_format:"unixNano"`
}
tests := []bindTestData{
{need: &needFixDurationEmpty{}, got: &needFixDurationEmpty{}, in: http.Header{"duration": []string{}}},
{need: &needFixUnixNanoEmpty{}, got: &needFixUnixNanoEmpty{}, in: http.Header{"createTime": []string{}}},
}
for _, v := range tests {
err := mapForm(v.got, v.in)
assert.NoError(t, err)
assert.Equal(t, v.need, v.got)
}
}

View File

@ -267,6 +267,11 @@ func setTimeField(val string, structField reflect.StructField, value reflect.Val
timeFormat = time.RFC3339
}
if val == "" {
value.Set(reflect.ValueOf(time.Time{}))
return nil
}
switch tf := strings.ToLower(timeFormat); tf {
case "unix", "unixnano":
tv, err := strconv.ParseInt(val, 10, 0)
@ -285,11 +290,6 @@ func setTimeField(val string, structField reflect.StructField, value reflect.Val
}
if val == "" {
value.Set(reflect.ValueOf(time.Time{}))
return nil
}
l := time.Local
if isUTC, _ := strconv.ParseBool(structField.Tag.Get("time_utc")); isUTC {
l = time.UTC
@ -333,6 +333,10 @@ func setSlice(vals []string, value reflect.Value, field reflect.StructField) err
}
func setTimeDuration(val string, value reflect.Value, field reflect.StructField) error {
if val == "" {
val = "0"
}
d, err := time.ParseDuration(val)
if err != nil {
return err