Skip to content

Context Bind: Regression when parsing arrays from multipart/form-data #2731

Open
@benpate

Description

@benpate

Issue Description

The code below works in echo v4.12.0, but breaks in v4.13.2. Previously, when reading a request body encoded with multipart/form-data, multiple values for a single variable name would be returned as a slice of strings. Now, in v4.13.2, only the first value is returned.

I believe there was some work around this area with the 4.13.0 release but I haven't dug into the code enough to say what's causing the issue.

This is a problem because it silently broke parts of my application that were expecting a slice but received something else.

Anyway, test case:

Working code to debug

package test

import (
	"bufio"
	"net/http"
	"strings"
	"testing"

	"github.com/labstack/echo/v4"
	"github.com/stretchr/testify/require"
)

func TestEchoBinder(t *testing.T) {

	// Read the HTTP request
	request, err := getTestRequest()
	require.Nil(t, err)

	// Mock a new Echo context
	ctx := echo.New().NewContext(request, nil)

	// Try to bind the request to a map of any
	data := map[string]any{}
	err = ctx.Bind(&data)
	require.Nil(t, err)

	// Verify that the "ima_slice" value is actually a slice
	// This fails on version 4.13.2 but passes on version 4.12.0
	require.Equal(t, []string{"WEBHOOK", "OTHER"}, data["ima_slice"])
}

// getTestRequest mocks an HTTP request with a multipart form body
func getTestRequest() (*http.Request, error) {

	// Here's the body of the request.  Note two values for "ima_slice"
	body := `POST /6692c69bfe80a9aacf125b0d/edit HTTP/1.1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryVfyfBnHAjBwnl9dd
Accept: */*

------WebKitFormBoundaryVfyfBnHAjBwnl9dd
Content-Disposition: form-data; name="ima_slice"

WEBHOOK
------WebKitFormBoundaryVfyfBnHAjBwnl9dd
Content-Disposition: form-data; name="ima_slice"

OTHER
------WebKitFormBoundaryVfyfBnHAjBwnl9dd--
`

	// Create a new HTTP request
	reader := strings.NewReader(body)
	bufferedReader := bufio.NewReader(reader)
	result, err := http.ReadRequest(bufferedReader)
	return result, err
}

Version/commit

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions