return a custom error when body size limit is exceeded (#5675)

This commit is contained in:
Alessandro Ros
2026-04-21 19:00:30 +02:00
committed by GitHub
parent 690905e4be
commit 2589c99639
14 changed files with 168 additions and 15 deletions
+1 -2
View File
@@ -1,7 +1,6 @@
package api //nolint:revive
import (
"io"
"net/http"
"github.com/bluenviron/mediamtx/internal/conf"
@@ -19,7 +18,7 @@ func (a *API) onConfigGlobalGet(ctx *gin.Context) {
func (a *API) onConfigGlobalPatch(ctx *gin.Context) {
var c conf.OptionalGlobal
err := jsonwrapper.Decode(io.LimitReader(ctx.Request.Body, maxInboundConfigSize), &c)
err := jsonwrapper.Decode(&customLimitReader{ctx.Request.Body, maxInboundConfigSize}, &c)
if err != nil {
a.writeError(ctx, http.StatusBadRequest, err)
return
+1 -2
View File
@@ -1,7 +1,6 @@
package api //nolint:revive
import (
"io"
"net/http"
"github.com/bluenviron/mediamtx/internal/conf"
@@ -19,7 +18,7 @@ func (a *API) onConfigPathDefaultsGet(ctx *gin.Context) {
func (a *API) onConfigPathDefaultsPatch(ctx *gin.Context) {
var p conf.OptionalPath
err := jsonwrapper.Decode(io.LimitReader(ctx.Request.Body, maxInboundConfigSize), &p)
err := jsonwrapper.Decode(&customLimitReader{ctx.Request.Body, maxInboundConfigSize}, &p)
if err != nil {
a.writeError(ctx, http.StatusBadRequest, err)
return
+3 -4
View File
@@ -3,7 +3,6 @@ package api //nolint:revive
import (
"errors"
"fmt"
"io"
"net/http"
"github.com/bluenviron/mediamtx/internal/conf"
@@ -64,7 +63,7 @@ func (a *API) onConfigPathsAdd(ctx *gin.Context) { //nolint:dupl
}
var p conf.OptionalPath
err := jsonwrapper.Decode(io.LimitReader(ctx.Request.Body, maxInboundConfigSize), &p)
err := jsonwrapper.Decode(&customLimitReader{ctx.Request.Body, maxInboundConfigSize}, &p)
if err != nil {
a.writeError(ctx, http.StatusBadRequest, err)
return
@@ -101,7 +100,7 @@ func (a *API) onConfigPathsPatch(ctx *gin.Context) { //nolint:dupl
}
var p conf.OptionalPath
err := jsonwrapper.Decode(io.LimitReader(ctx.Request.Body, maxInboundConfigSize), &p)
err := jsonwrapper.Decode(&customLimitReader{ctx.Request.Body, maxInboundConfigSize}, &p)
if err != nil {
a.writeError(ctx, http.StatusBadRequest, err)
return
@@ -142,7 +141,7 @@ func (a *API) onConfigPathsReplace(ctx *gin.Context) { //nolint:dupl
}
var p conf.OptionalPath
err := jsonwrapper.Decode(io.LimitReader(ctx.Request.Body, maxInboundConfigSize), &p)
err := jsonwrapper.Decode(&customLimitReader{ctx.Request.Body, maxInboundConfigSize}, &p)
if err != nil {
a.writeError(ctx, http.StatusBadRequest, err)
return
+26
View File
@@ -0,0 +1,26 @@
package api
import (
"fmt"
"io"
)
var errSizeExceeded = fmt.Errorf("size exceeds maximum allowed")
// like io.LimitReader, but returns a dedicated error if the limit is exceeded.
type customLimitReader struct {
r io.Reader
n int64
}
func (l *customLimitReader) Read(p []byte) (n int, err error) {
if l.n <= 0 {
return 0, errSizeExceeded
}
if int64(len(p)) > l.n {
p = p[0:l.n]
}
n, err = l.r.Read(p)
l.n -= int64(n)
return
}
+26
View File
@@ -0,0 +1,26 @@
package auth
import (
"fmt"
"io"
)
var errSizeExceeded = fmt.Errorf("size exceeds maximum allowed")
// like io.LimitReader, but returns a dedicated error if the limit is exceeded.
type customLimitReader struct {
r io.Reader
n int64
}
func (l *customLimitReader) Read(p []byte) (n int, err error) {
if l.n <= 0 {
return 0, errSizeExceeded
}
if int64(len(p)) > l.n {
p = p[0:l.n]
}
n, err = l.r.Read(p)
l.n -= int64(n)
return
}
+2 -2
View File
@@ -235,7 +235,7 @@ func (m *Manager) authenticateHTTP(req *Request, token string) (string, error) {
defer res.Body.Close()
if res.StatusCode < 200 || res.StatusCode > 299 {
resBody, err2 := io.ReadAll(io.LimitReader(res.Body, maxInboundBodySize))
resBody, err2 := io.ReadAll(&customLimitReader{res.Body, maxInboundBodySize})
if err2 == nil && len(resBody) != 0 {
return "", fmt.Errorf("server replied with code %d: %s", res.StatusCode, string(resBody))
}
@@ -306,7 +306,7 @@ func (m *Manager) pullJWTJWKS() (jwt.Keyfunc, error) {
defer res.Body.Close()
var raw json.RawMessage
err = json.NewDecoder(io.LimitReader(res.Body, maxInboundBodySize)).Decode(&raw)
err = json.NewDecoder(&customLimitReader{res.Body, maxInboundBodySize}).Decode(&raw)
if err != nil {
return nil, err
}
+1 -1
View File
@@ -264,7 +264,7 @@ func (c *Client) postOffer(
return nil, fmt.Errorf("ETag is missing")
}
sdp, err := io.ReadAll(io.LimitReader(res.Body, maxInboundSDPSize))
sdp, err := io.ReadAll(&customLimitReader{res.Body, maxInboundSDPSize})
if err != nil {
return nil, err
}
@@ -0,0 +1,26 @@
package whip
import (
"fmt"
"io"
)
var errSizeExceeded = fmt.Errorf("size exceeds maximum allowed")
// like io.LimitReader, but returns a dedicated error if the limit is exceeded.
type customLimitReader struct {
r io.Reader
n int64
}
func (l *customLimitReader) Read(p []byte) (n int, err error) {
if l.n <= 0 {
return 0, errSizeExceeded
}
if int64(len(p)) > l.n {
p = p[0:l.n]
}
n, err = l.r.Read(p)
l.n -= int64(n)
return
}
@@ -0,0 +1,26 @@
package main
import (
"fmt"
"io"
)
var errSizeExceeded = fmt.Errorf("size exceeds maximum allowed")
// like io.LimitReader, but returns a dedicated error if the limit is exceeded.
type customLimitReader struct {
r io.Reader
n int64
}
func (l *customLimitReader) Read(p []byte) (n int, err error) {
if l.n <= 0 {
return 0, errSizeExceeded
}
if int64(len(p)) > l.n {
p = p[0:l.n]
}
n, err = l.r.Read(p)
l.n -= int64(n)
return
}
+1 -1
View File
@@ -38,7 +38,7 @@ func do() error {
return fmt.Errorf("bad status code: %v", res.StatusCode)
}
zipBuf, err := io.ReadAll(io.LimitReader(res.Body, maxInboundHLSJSSize))
zipBuf, err := io.ReadAll(&customLimitReader{res.Body, maxInboundHLSJSSize})
if err != nil {
return err
}
@@ -0,0 +1,26 @@
package webrtc
import (
"fmt"
"io"
)
var errSizeExceeded = fmt.Errorf("size exceeds maximum allowed")
// like io.LimitReader, but returns a dedicated error if the limit is exceeded.
type customLimitReader struct {
r io.Reader
n int64
}
func (l *customLimitReader) Read(p []byte) (n int, err error) {
if l.n <= 0 {
return 0, errSizeExceeded
}
if int64(len(p)) > l.n {
p = p[0:l.n]
}
n, err = l.r.Read(p)
l.n -= int64(n)
return
}
+2 -2
View File
@@ -194,7 +194,7 @@ func (s *httpServer) onWHIPPost(ctx *gin.Context, pathName string, publish bool)
return
}
offer, err := io.ReadAll(io.LimitReader(ctx.Request.Body, maxInboundSDPSize))
offer, err := io.ReadAll(&customLimitReader{ctx.Request.Body, maxInboundSDPSize})
if err != nil {
return
}
@@ -260,7 +260,7 @@ func (s *httpServer) onWHIPPatch(ctx *gin.Context, pathName string, rawSecret st
return
}
byts, err := io.ReadAll(io.LimitReader(ctx.Request.Body, maxInboundSDPSize))
byts, err := io.ReadAll(&customLimitReader{ctx.Request.Body, maxInboundSDPSize})
if err != nil {
return
}
@@ -0,0 +1,26 @@
package main
import (
"fmt"
"io"
)
var errSizeExceeded = fmt.Errorf("size exceeds maximum allowed")
// like io.LimitReader, but returns a dedicated error if the limit is exceeded.
type customLimitReader struct {
r io.Reader
n int64
}
func (l *customLimitReader) Read(p []byte) (n int, err error) {
if l.n <= 0 {
return 0, errSizeExceeded
}
if int64(len(p)) > l.n {
p = p[0:l.n]
}
n, err = l.r.Read(p)
l.n -= int64(n)
return
}
@@ -79,7 +79,7 @@ func doSingle(version string, f string) error {
return fmt.Errorf("bad status code: %v", res.StatusCode)
}
buf, err := io.ReadAll(io.LimitReader(res.Body, maxInboundRPICameraSize))
buf, err := io.ReadAll(&customLimitReader{res.Body, maxInboundRPICameraSize})
if err != nil {
return err
}