@marcel91200 / caddy Mirror · read-only / commits / c65c2483
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 11, 03:30 UTC

caddyhttp: document that negative idle timeouts disable them (#8146)

read_idle_timeout and write_idle_timeout default to 1 minute when zero, and the wrappers are only installed for positive values, so a negative value already disables them. Document it and cover it with tests, since it is the only way to opt out, for instance behind a reverse proxy that already protects from slow clients.

Kévin Dunglas committed Oct 6, 2026 at 00:23 UTC c65c2483365e2ef5102d6e3c0c73ef7bbb516d78
3 files changed +66 -2
caddytest/integration/caddyfile_adapt/global_server_options_idle_disabled.caddyfiletest new
+27
@@ -0,0 +1,27 @@
1 +{
2 + servers {
3 + timeouts {
4 + read_body_idle -1s
5 + write_idle -1s
6 + }
7 + }
8 +}
9 +
10 +:80 {
11 +}
12 +----------
13 +{
14 + "apps": {
15 + "http": {
16 + "servers": {
17 + "srv0": {
18 + "listen": [
19 + ":80"
20 + ],
21 + "read_idle_timeout": -1000000000,
22 + "write_idle_timeout": -1000000000
23 + }
24 + }
25 + }
26 + }
27 +}
modules/caddyhttp/server.go
+4 -2
@@ -74,7 +74,8 @@ type Server struct {
74 // it mitigates slowloris-style attacks without penalizing large
75 // uploads from legitimately slow clients. Combine with ReadTimeout
76 // for a hard ceiling on top.
77 - // Default is 1 minute.
77 + // Default is 1 minute. A negative value disables it, for instance
78 + // behind a proxy that already buffers request bodies.
79 ReadIdleTimeout caddy.Duration `json:"read_idle_timeout,omitempty"`
80
81 // ReadMinRate, if set, requires the client to sustain at least this
@@ -97,7 +98,8 @@ type Server struct {
98 // response, or pauses between writes (e.g. SSE), is unaffected as
99 // long as each individual write keeps making progress. Combine
100 // with WriteTimeout for a hard ceiling on top.
100 - // Default is 1 minute.
101 + // Default is 1 minute. A negative value disables it, for instance
102 + // behind a proxy that already times out slow clients.
103 WriteIdleTimeout caddy.Duration `json:"write_idle_timeout,omitempty"`
104
105 // WriteMinRate is like ReadMinRate, but for writes to the client.
modules/caddyhttp/server_test.go
+35
@@ -1534,3 +1534,38 @@ func TestServer_ServeHTTP_DelayedHandlerErrorWritesErrorStatus(t *testing.T) {
1534 })
1535 }
1536 }
1537 +
1538 +func TestServer_ServeHTTP_IdleTimeouts(t *testing.T) {
1539 + for _, tc := range []struct {
1540 + name string
1541 + timeout caddy.Duration
1542 + applied bool
1543 + }{
1544 + {name: "positive", timeout: caddy.Duration(time.Minute), applied: true},
1545 + {name: "negative disables", timeout: -1},
1546 + } {
1547 + t.Run(tc.name, func(t *testing.T) {
1548 + var reader *IdleTimeoutReader
1549 + var writer *IdleTimeoutWriter
1550 + s := &Server{
1551 + ReadIdleTimeout: tc.timeout,
1552 + WriteIdleTimeout: tc.timeout,
1553 + logger: zap.NewNop(),
1554 + errorLogger: zap.NewNop(),
1555 + primaryHandlerChain: HandlerFunc(func(_ http.ResponseWriter, r *http.Request) error {
1556 + reader, writer = IdleTimeoutsFromContext(r.Context())
1557 + return nil
1558 + }),
1559 + }
1560 + ts := httptest.NewServer(http.HandlerFunc(s.ServeHTTP))
1561 + t.Cleanup(ts.Close)
1562 +
1563 + resp, err := ts.Client().Post(ts.URL, "text/plain", strings.NewReader("x"))
1564 + require.NoError(t, err)
1565 + resp.Body.Close()
1566 +
1567 + assert.Equal(t, tc.applied, reader != nil)
1568 + assert.Equal(t, tc.applied, writer != nil)
1569 + })
1570 + }
1571 +}