diff --git a/binding/form_mapping.go b/binding/form_mapping.go index 540bbbb8..dd46fb4c 100644 --- a/binding/form_mapping.go +++ b/binding/form_mapping.go @@ -175,6 +175,15 @@ func setByForm(value reflect.Value, field reflect.StructField, form map[string][ if !ok { vs = []string{opt.defaultValue} } + + switch value.Interface().(type) { + case []byte: + if len(vs) > 0 { + value.Set(reflect.ValueOf([]byte(vs[0]))) + return true, nil + } + } + return true, setSlice(vs, value, field) case reflect.Array: if !ok { diff --git a/binding/form_mapping_test.go b/binding/form_mapping_test.go index 93d6a92f..9f26cedf 100644 --- a/binding/form_mapping_test.go +++ b/binding/form_mapping_test.go @@ -269,6 +269,15 @@ func TestMappingStructField(t *testing.T) { assert.Equal(t, 9, s.J.I) } +func TestByteArray(t *testing.T) { + var s struct { + B []byte + } + err := mappingByPtr(&s, formSource{"B": {"hello"}}, "form") + assert.NoError(t, err) + assert.Equal(t, []byte("hello"), s.B) +} + func TestMappingMapField(t *testing.T) { var s struct { M map[string]int diff --git a/binding/multipart_form_mapping.go b/binding/multipart_form_mapping.go index 4ebe8326..d11c93aa 100644 --- a/binding/multipart_form_mapping.go +++ b/binding/multipart_form_mapping.go @@ -6,6 +6,7 @@ package binding import ( "errors" + "io/ioutil" "mime/multipart" "net/http" "reflect" @@ -14,6 +15,7 @@ import ( type multipartRequest http.Request var _ setter = (*multipartRequest)(nil) +var ConstructionFailure = false var ( // ErrMultiFileHeader multipart.FileHeader invalid @@ -47,6 +49,27 @@ func setByMultipartFormFile(value reflect.Value, field reflect.StructField, file return true, nil } case reflect.Slice: + switch value.Interface().(type) { + case []byte: + fd, err := files[0].Open() + if err != nil { + return false, err + } + defer fd.Close() + c, err := ioutil.ReadAll(fd) + + if ConstructionFailure { + err = errors.New("test use") + } + + if err != nil { + return false, err + } + + value.Set(reflect.ValueOf(c)) + return true, nil + } + slice := reflect.MakeSlice(value.Type(), len(files), len(files)) isSet, err = setArrayOfMultipartFormFiles(slice, field, files) if err != nil || !isSet { diff --git a/binding/multipart_form_mapping_test.go b/binding/multipart_form_mapping_test.go index 4e97c0f0..c9dffb43 100644 --- a/binding/multipart_form_mapping_test.go +++ b/binding/multipart_form_mapping_test.go @@ -14,6 +14,55 @@ import ( "github.com/stretchr/testify/assert" ) +func TestFormMultipartBindingOneFileToBytesFail1(t *testing.T) { + var test struct { + Voice []byte `form:"voice"` + } + + file := testFile{"voice", "test.pcm", []byte("pcm pcm pcm")} + req := createRequestMultipartFiles(t, file) + + err := req.ParseMultipartForm(3) + assert.NoError(t, err) + + err = req.MultipartForm.RemoveAll() + assert.NoError(t, err) + + err = mappingByPtr(&test, (*multipartRequest)(req), "form") + assert.Error(t, err) +} + +func TestFormMultipartBindingOneFileToBytesFail2(t *testing.T) { + var test struct { + Voice []byte `form:"voice"` + } + + file := testFile{"voice", "test.pcm", []byte("pcm pcm pcm")} + req := createRequestMultipartFiles(t, file) + + ConstructionFailure = true + + err := req.ParseMultipartForm(3) + assert.NoError(t, err) + + err = mappingByPtr(&test, (*multipartRequest)(req), "form") + assert.Error(t, err) + ConstructionFailure = false +} + +func TestFormMultipartBindingOneFileToBytesArray(t *testing.T) { + var test struct { + Voice []byte `form:"voice"` + } + + file := testFile{"voice", "test.pcm", []byte("pcm pcm pcm")} + req := createRequestMultipartFiles(t, file) + err := FormMultipart.Bind(req, &test) + assert.NoError(t, err) + + assert.Equal(t, test.Voice, []byte("pcm pcm pcm")) +} + func TestFormMultipartBindingBindOneFile(t *testing.T) { var s struct { FileValue multipart.FileHeader `form:"file"`