Skip to content

Commit 283d1ac

Browse files
committed
fix CSRF middleware not being able to extract token from multipart/form-data form
1 parent b445958 commit 283d1ac

File tree

2 files changed

+31
-12
lines changed

2 files changed

+31
-12
lines changed

middleware/extractor.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,8 @@ func valuesFromCookie(name string) ValuesExtractor {
168168
// valuesFromForm returns a function that extracts values from the form field.
169169
func valuesFromForm(name string) ValuesExtractor {
170170
return func(c echo.Context) ([]string, error) {
171-
if parseErr := c.Request().ParseForm(); parseErr != nil {
172-
return nil, fmt.Errorf("valuesFromForm parse form failed: %w", parseErr)
171+
if c.Request().Form == nil {
172+
_ = c.Request().ParseMultipartForm(32 << 20) // same what `c.Request().FormValue(name)` does
173173
}
174174
values := c.Request().Form[name]
175175
if len(values) == 0 {

middleware/extractor_test.go

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package middleware
22

33
import (
4+
"bytes"
45
"fmt"
56
"github.com/labstack/echo/v4"
67
"github.com/stretchr/testify/assert"
8+
"mime/multipart"
79
"net/http"
810
"net/http/httptest"
911
"net/url"
@@ -499,6 +501,25 @@ func TestValuesFromForm(t *testing.T) {
499501
return req
500502
}
501503

504+
exampleMultiPartFormRequest := func(mod func(w *multipart.Writer)) *http.Request {
505+
var b bytes.Buffer
506+
w := multipart.NewWriter(&b)
507+
w.WriteField("name", "Jon Snow")
508+
w.WriteField("emails[]", "jon@labstack.com")
509+
if mod != nil {
510+
mod(w)
511+
}
512+
513+
fw, _ := w.CreateFormFile("upload", "my.file")
514+
fw.Write([]byte(`<div>hi</div>`))
515+
w.Close()
516+
517+
req := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(b.String()))
518+
req.Header.Add(echo.HeaderContentType, w.FormDataContentType())
519+
520+
return req
521+
}
522+
502523
var testCases = []struct {
503524
name string
504525
givenRequest *http.Request
@@ -520,6 +541,14 @@ func TestValuesFromForm(t *testing.T) {
520541
whenName: "emails[]",
521542
expectValues: []string{"jon@labstack.com", "snow@labstack.com"},
522543
},
544+
{
545+
name: "ok, POST multipart/form, multiple value",
546+
givenRequest: exampleMultiPartFormRequest(func(w *multipart.Writer) {
547+
w.WriteField("emails[]", "snow@labstack.com")
548+
}),
549+
whenName: "emails[]",
550+
expectValues: []string{"jon@labstack.com", "snow@labstack.com"},
551+
},
523552
{
524553
name: "ok, GET form, single value",
525554
givenRequest: exampleGetFormRequest(nil),
@@ -540,16 +569,6 @@ func TestValuesFromForm(t *testing.T) {
540569
whenName: "nope",
541570
expectError: errFormExtractorValueMissing.Error(),
542571
},
543-
{
544-
name: "nok, POST form, form parsing error",
545-
givenRequest: func() *http.Request {
546-
req := httptest.NewRequest(http.MethodPost, "/", nil)
547-
req.Body = nil
548-
return req
549-
}(),
550-
whenName: "name",
551-
expectError: "valuesFromForm parse form failed: missing form body",
552-
},
553572
{
554573
name: "ok, cut values over extractorLimit",
555574
givenRequest: examplePostFormRequest(func(v *url.Values) {

0 commit comments

Comments
 (0)