feat: limit response body sizes

fasthttp allocates the body from the declared Content-Length before
reading it, so a server could exhaust memory by declaring a size it
never sends. The new max response body config bounds every response,
defaults to 10MiB and accepts sizes like 10MiB or 2MB. Scripts get the
same as a maxBodySize option on http().
This commit is contained in:
aykhans committed 2026-09-28 22:49:39 +04:00
1 parent 412a02fea3
commit f1d91e3d77
17 files changed
+452 -147

No files matched your search

+21
View File
@@ -21,6 +21,7 @@ type HTTPRequest struct {
Timeout time.Duration // zero means the doer's default timeout
Insecure bool
MaxRedirects int
MaxBodySize int64 // zero means no limit
}
// HTTPResponse is the response returned to a script by the http.* functions.
@@ -66,6 +67,9 @@ const httpDefaultMethod = http.MethodGet
// httpMaxRedirectsLimit is the highest maxRedirects a script may ask for.
const httpMaxRedirectsLimit = 100
// httpMaxBodySizeLimit is the highest maxBodySize a script may ask for, 1 TiB.
const httpMaxBodySizeLimit int64 = 1 << 40
// Option keys accepted by the http function.
const (
httpOptionMethod = "method"
@@ -76,6 +80,7 @@ const (
httpOptionTimeout = "timeout"
httpOptionInsecure = "insecure"
httpOptionMaxRedirects = "maxRedirects"
httpOptionMaxBodySize = "maxBodySize"
)
// httpBridge connects http to the doer. Calls only work while transform runs.
@@ -118,6 +123,22 @@ func parseHTTPMaxRedirects(count float64) (int, error) {
return int(count), nil
}
// parseHTTPMaxBodySize checks that the body limit is a non-negative whole number.
// It can return the following errors:
// - types.ScriptHTTPOptionError
func parseHTTPMaxBodySize(size float64) (int64, error) {
if math.IsNaN(size) || size < 0 || size > float64(httpMaxBodySizeLimit) || size != math.Trunc(size) {
return 0, types.NewScriptHTTPOptionError(
httpOptionMaxBodySize,
types.NewScriptTypeError(
"a whole number of bytes between 0 and "+strconv.FormatInt(httpMaxBodySizeLimit, 10),
strconv.FormatFloat(size, 'g', -1, 64),
),
)
}
return int64(size), nil
}
// parseHTTPTimeout parses a Go duration string such as "500ms" or "2s".
// It can return the following errors:
// - types.ScriptHTTPOptionError