1
0
mirror of https://github.com/labstack/echo.git synced 2025-11-25 22:32:23 +02:00

Fix DefaultBinder empty body handling for unknown ContentLength

Fix issue where POST requests with empty bodies and ContentLength=-1
(unknown/chunked encoding) incorrectly fail with 415 Unsupported Media Type.

The DefaultBinder.BindBody method now properly detects truly empty bodies
when ContentLength=-1 by peeking at the first byte. If no content is found,
it returns early without error. If content exists, it reconstructs the body
to preserve the original data.

Fixes #2813

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Vishal Rana
2025-09-15 18:47:57 -07:00
parent 61da50fefc
commit 2fb84197e9
2 changed files with 25 additions and 0 deletions

17
bind.go
View File

@@ -8,6 +8,7 @@ import (
"encoding/xml"
"errors"
"fmt"
"io"
"mime/multipart"
"net/http"
"reflect"
@@ -71,6 +72,22 @@ func (b *DefaultBinder) BindBody(c Context, i interface{}) (err error) {
return
}
// For unknown ContentLength (-1), check if body is actually empty
if req.ContentLength == -1 {
// Peek at the first byte to see if there's any content
var buf [1]byte
n, readErr := req.Body.Read(buf[:])
if readErr != nil && readErr != io.EOF {
return NewHTTPError(http.StatusBadRequest, readErr.Error()).SetInternal(readErr)
}
if n == 0 {
// Body is empty, return without error
return
}
// There's content, put the byte back by creating a new reader
req.Body = io.NopCloser(io.MultiReader(strings.NewReader(string(buf[:n])), req.Body))
}
// mediatype is found like `mime.ParseMediaType()` does it
base, _, _ := strings.Cut(req.Header.Get(HeaderContentType), ";")
mediatype := strings.TrimSpace(base)

View File

@@ -1082,6 +1082,14 @@ func TestDefaultBinder_BindBody(t *testing.T) {
givenContent: strings.NewReader(""),
expect: &Node{ID: 0, Node: ""},
},
{
name: "ok, POST with empty body and ContentLength -1 (Issue #2813)",
givenURL: "/api/real_node/endpoint?node=xxx",
givenMethod: http.MethodPost,
givenContent: strings.NewReader(""),
whenChunkedBody: true, // This sets ContentLength to -1
expect: &Node{ID: 0, Node: ""},
},
{
name: "ok, JSON POST bind to struct with: path + query + chunked body",
givenURL: "/api/real_node/endpoint?node=xxx",