Преглед на файлове

Restored support of multipart/form-data

Maksimov Sergey преди 10 години
родител
ревизия
e46f4980b9
променени са 4 файла, в които са добавени 99 реда и са изтрити 3 реда
  1. 6 3
      binding/binding.go
  2. 3 0
      binding/binding_test.go
  3. 25 0
      binding/form_multipart.go
  4. 65 0
      context_test.go

+ 6 - 3
binding/binding.go

@@ -28,9 +28,10 @@ type Binding interface {
 var validate = validator.New("binding", validator.BakedInValidators)
 
 var (
-	JSON = jsonBinding{}
-	XML  = xmlBinding{}
-	Form = formBinding{}
+	XML           = xmlBinding{}
+	JSON          = jsonBinding{}
+	Form          = formBinding{}
+	MultipartForm = multipartFormBinding{}
 )
 
 func Default(method, contentType string) Binding {
@@ -42,6 +43,8 @@ func Default(method, contentType string) Binding {
 			return JSON
 		case MIMEXML, MIMEXML2:
 			return XML
+		case MIMEMultipartPOSTForm:
+			return MultipartForm
 		default:
 			return Form
 		}

+ 3 - 0
binding/binding_test.go

@@ -33,6 +33,9 @@ func TestBindingDefault(t *testing.T) {
 
 	assert.Equal(t, Default("POST", MIMEPOSTForm), Form)
 	assert.Equal(t, Default("DELETE", MIMEPOSTForm), Form)
+
+	assert.Equal(t, Default("POST", MIMEMultipartPOSTForm), MultipartForm)
+	assert.Equal(t, Default("DELETE", MIMEMultipartPOSTForm), MultipartForm)
 }
 
 func TestBindingJSON(t *testing.T) {

+ 25 - 0
binding/form_multipart.go

@@ -0,0 +1,25 @@
+// Copyright 2014 Manu Martinez-Almeida.  All rights reserved.
+// Use of this source code is governed by a MIT style
+// license that can be found in the LICENSE file.
+
+package binding
+
+import "net/http"
+
+const MAX_MEMORY = 1 * 1024 * 1024
+
+type multipartFormBinding struct{}
+
+func (_ multipartFormBinding) Name() string {
+	return "multipart form"
+}
+
+func (_ multipartFormBinding) Bind(req *http.Request, obj interface{}) error {
+	if err := req.ParseMultipartForm(MAX_MEMORY); err != nil {
+		return err
+	}
+	if err := mapForm(obj, req.Form); err != nil {
+		return err
+	}
+	return Validate(obj)
+}

+ 65 - 0
context_test.go

@@ -8,6 +8,7 @@ import (
 	"bytes"
 	"errors"
 	"html/template"
+	"mime/multipart"
 	"net/http"
 	"net/http/httptest"
 	"testing"
@@ -33,6 +34,26 @@ func createTestContext() (c *Context, w *httptest.ResponseRecorder, r *Engine) {
 	return
 }
 
+func createMultipartForm() (body *bytes.Buffer, header string, err error) {
+	boundary := "--testboundary"
+	header = MIMEMultipartPOSTForm + "; boundary=" + boundary
+	body = &bytes.Buffer{}
+
+	mw := multipart.NewWriter(body)
+	defer mw.Close()
+
+	if err = mw.SetBoundary(boundary); err != nil {
+		return
+	}
+	if err = mw.WriteField("foo", "bar"); err != nil {
+		return
+	}
+	if err = mw.WriteField("bar", "foo"); err != nil {
+		return
+	}
+	return
+}
+
 func TestContextReset(t *testing.T) {
 	router := New()
 	c := router.allocateContext()
@@ -444,6 +465,28 @@ func TestContextAutoBind(t *testing.T) {
 	assert.Equal(t, w.Body.Len(), 0)
 }
 
+func TestContextMultipartPostFormAutoBind(t *testing.T) {
+	c, w, _ := createTestContext()
+
+	var obj struct {
+		Foo string `form:"foo"`
+		Bar string `form:"bar"`
+	}
+
+	body, header, err := createMultipartForm()
+	if err != nil {
+		t.Error(err)
+	}
+
+	c.Request, _ = http.NewRequest("POST", "/", body)
+	c.Request.Header.Add("Content-Type", header)
+
+	assert.NoError(t, c.Bind(&obj))
+	assert.Equal(t, obj.Bar, "foo")
+	assert.Equal(t, obj.Foo, "bar")
+	assert.Equal(t, w.Body.Len(), 0)
+}
+
 func TestContextBadAutoBind(t *testing.T) {
 	c, w, _ := createTestContext()
 	c.Request, _ = http.NewRequest("POST", "http://example.com", bytes.NewBufferString("\"foo\":\"bar\", \"bar\":\"foo\"}"))
@@ -477,6 +520,28 @@ func TestContextBindWith(t *testing.T) {
 	assert.Equal(t, w.Body.Len(), 0)
 }
 
+func TestContextMultipartBindWith(t *testing.T) {
+	c, w, _ := createTestContext()
+
+	var obj struct {
+		Foo string `form:"foo"`
+		Bar string `form:"bar"`
+	}
+
+	body, header, err := createMultipartForm()
+	if err != nil {
+		t.Error(err)
+	}
+
+	c.Request, _ = http.NewRequest("POST", "/", body)
+	c.Request.Header.Add("Content-Type", header)
+
+	assert.NoError(t, c.BindWith(&obj, binding.MultipartForm))
+	assert.Equal(t, obj.Bar, "foo")
+	assert.Equal(t, obj.Foo, "bar")
+	assert.Equal(t, w.Body.Len(), 0)
+}
+
 func TestContextGolangContext(t *testing.T) {
 	c, _, _ := createTestContext()
 	c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}"))