Skip to content

Commit 2fb8419

Browse files
vishrclaude
andcommitted
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 <[email protected]>
1 parent 61da50f commit 2fb8419

File tree

2 files changed

+25
-0
lines changed

2 files changed

+25
-0
lines changed

bind.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"encoding/xml"
99
"errors"
1010
"fmt"
11+
"io"
1112
"mime/multipart"
1213
"net/http"
1314
"reflect"
@@ -71,6 +72,22 @@ func (b *DefaultBinder) BindBody(c Context, i interface{}) (err error) {
7172
return
7273
}
7374

75+
// For unknown ContentLength (-1), check if body is actually empty
76+
if req.ContentLength == -1 {
77+
// Peek at the first byte to see if there's any content
78+
var buf [1]byte
79+
n, readErr := req.Body.Read(buf[:])
80+
if readErr != nil && readErr != io.EOF {
81+
return NewHTTPError(http.StatusBadRequest, readErr.Error()).SetInternal(readErr)
82+
}
83+
if n == 0 {
84+
// Body is empty, return without error
85+
return
86+
}
87+
// There's content, put the byte back by creating a new reader
88+
req.Body = io.NopCloser(io.MultiReader(strings.NewReader(string(buf[:n])), req.Body))
89+
}
90+
7491
// mediatype is found like `mime.ParseMediaType()` does it
7592
base, _, _ := strings.Cut(req.Header.Get(HeaderContentType), ";")
7693
mediatype := strings.TrimSpace(base)

bind_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,6 +1082,14 @@ func TestDefaultBinder_BindBody(t *testing.T) {
10821082
givenContent: strings.NewReader(""),
10831083
expect: &Node{ID: 0, Node: ""},
10841084
},
1085+
{
1086+
name: "ok, POST with empty body and ContentLength -1 (Issue #2813)",
1087+
givenURL: "/api/real_node/endpoint?node=xxx",
1088+
givenMethod: http.MethodPost,
1089+
givenContent: strings.NewReader(""),
1090+
whenChunkedBody: true, // This sets ContentLength to -1
1091+
expect: &Node{ID: 0, Node: ""},
1092+
},
10851093
{
10861094
name: "ok, JSON POST bind to struct with: path + query + chunked body",
10871095
givenURL: "/api/real_node/endpoint?node=xxx",

0 commit comments

Comments
 (0)