@@ -32,6 +32,14 @@ func TestDecodeConfig(t *testing.T) {
3232 got .MaxTunnelsPerIP ,
3333 )
3434 }
35+ if got .MaxIdleConns != 100 || got .MaxIdleConnsPerHost != 10 || time .Duration (got .IdleConnTimeout ) != 90 * time .Second {
36+ t .Errorf (
37+ "HTTP transport defaults = idle %d, idle/host %d, timeout %s; want 100, 10, 1m30s" ,
38+ got .MaxIdleConns ,
39+ got .MaxIdleConnsPerHost ,
40+ time .Duration (got .IdleConnTimeout ),
41+ )
42+ }
3543 },
3644 },
3745 {
@@ -44,6 +52,8 @@ func TestDecodeConfig(t *testing.T) {
4452 "max_connections_per_ip: 20" ,
4553 "max_tunnels: 50" ,
4654 "max_tunnels_per_ip: 5" ,
55+ "max_idle_conns: 80" ,
56+ "max_idle_conns_per_host: 8" ,
4757 "max_header_bytes: 32768" ,
4858 "auth_max_failures: 7" ,
4959 "allow_private_destinations: true" ,
@@ -52,6 +62,7 @@ func TestDecodeConfig(t *testing.T) {
5262 "tls_handshake_timeout: 3s" ,
5363 "tls_reload_interval: 350ms" ,
5464 "response_header_timeout: 4s" ,
65+ "idle_conn_timeout: 90s" ,
5566 "read_header_timeout: 5s" ,
5667 "idle_timeout: 6m" ,
5768 "tunnel_idle_timeout: 8m" ,
@@ -78,6 +89,8 @@ func TestDecodeConfig(t *testing.T) {
7889 "MaxConnectionsPerIP" : 20 ,
7990 "MaxTunnels" : 50 ,
8091 "MaxTunnelsPerIP" : 5 ,
92+ "MaxIdleConns" : 80 ,
93+ "MaxIdleConnsPerHost" : 8 ,
8194 "MaxHeaderBytes" : 32768 ,
8295 "AuthMaxFailures" : 7 ,
8396 }
@@ -86,6 +99,8 @@ func TestDecodeConfig(t *testing.T) {
8699 "MaxConnectionsPerIP" : got .MaxConnectionsPerIP ,
87100 "MaxTunnels" : got .MaxTunnels ,
88101 "MaxTunnelsPerIP" : got .MaxTunnelsPerIP ,
102+ "MaxIdleConns" : got .MaxIdleConns ,
103+ "MaxIdleConnsPerHost" : got .MaxIdleConnsPerHost ,
89104 "MaxHeaderBytes" : got .MaxHeaderBytes ,
90105 "AuthMaxFailures" : got .AuthMaxFailures ,
91106 }
@@ -103,6 +118,7 @@ func TestDecodeConfig(t *testing.T) {
103118 "TLSHandshakeTimeout" : 3 * time .Second ,
104119 "TLSReloadInterval" : 350 * time .Millisecond ,
105120 "ResponseHeaderTimeout" : 4 * time .Second ,
121+ "IdleConnTimeout" : 90 * time .Second ,
106122 "ReadHeaderTimeout" : 5 * time .Second ,
107123 "IdleTimeout" : 6 * time .Minute ,
108124 "TunnelIdleTimeout" : 8 * time .Minute ,
@@ -115,6 +131,7 @@ func TestDecodeConfig(t *testing.T) {
115131 "TLSHandshakeTimeout" : time .Duration (got .TLSHandshakeTimeout ),
116132 "TLSReloadInterval" : time .Duration (got .TLSReloadInterval ),
117133 "ResponseHeaderTimeout" : time .Duration (got .ResponseHeaderTimeout ),
134+ "IdleConnTimeout" : time .Duration (got .IdleConnTimeout ),
118135 "ReadHeaderTimeout" : time .Duration (got .ReadHeaderTimeout ),
119136 "IdleTimeout" : time .Duration (got .IdleTimeout ),
120137 "TunnelIdleTimeout" : time .Duration (got .TunnelIdleTimeout ),
@@ -365,6 +382,13 @@ func TestValidateConfig(t *testing.T) {
365382 },
366383 wantMessage : "response_header_timeout must be greater than zero" ,
367384 },
385+ {
386+ name : "nonpositive idle connection timeout" ,
387+ mutate : func (config * Config ) {
388+ config .IdleConnTimeout = 0
389+ },
390+ wantMessage : "idle_conn_timeout must be greater than zero" ,
391+ },
368392 {
369393 name : "nonpositive read header timeout" ,
370394 mutate : func (config * Config ) {
@@ -435,6 +459,20 @@ func TestValidateConfig(t *testing.T) {
435459 },
436460 wantMessage : "max_tunnels_per_ip cannot exceed max_tunnels" ,
437461 },
462+ {
463+ name : "nonpositive maximum idle connections" ,
464+ mutate : func (config * Config ) {
465+ config .MaxIdleConns = 0
466+ },
467+ wantMessage : "max_idle_conns must be greater than zero" ,
468+ },
469+ {
470+ name : "nonpositive per-host idle connections" ,
471+ mutate : func (config * Config ) {
472+ config .MaxIdleConnsPerHost = 0
473+ },
474+ wantMessage : "max_idle_conns_per_host must be greater than zero" ,
475+ },
438476 {
439477 name : "nonpositive header limit" ,
440478 mutate : func (config * Config ) {
@@ -591,6 +629,8 @@ func TestApplyEnvOverridesParsesResourceLimits(t *testing.T) {
591629 "PROXY_MAX_CONNECTIONS_PER_IP" : "20" ,
592630 "PROXY_MAX_TUNNELS" : "50" ,
593631 "PROXY_MAX_TUNNELS_PER_IP" : "5" ,
632+ "PROXY_MAX_IDLE_CONNS" : "80" ,
633+ "PROXY_MAX_IDLE_CONNS_PER_HOST" : "8" ,
594634 "PROXY_MAX_HEADER_BYTES" : "32768" ,
595635 "PROXY_AUTH_MAX_FAILURES" : "7" ,
596636 "PROXY_ALLOW_PRIVATE_DESTINATIONS" : "true" ,
@@ -609,6 +649,9 @@ func TestApplyEnvOverridesParsesResourceLimits(t *testing.T) {
609649 if config .MaxTunnels != 50 || config .MaxTunnelsPerIP != 5 {
610650 t .Fatalf ("tunnel limits = %d/%d, want 50/5" , config .MaxTunnels , config .MaxTunnelsPerIP )
611651 }
652+ if config .MaxIdleConns != 80 || config .MaxIdleConnsPerHost != 8 {
653+ t .Fatalf ("HTTP idle connection limits = %d/%d, want 80/8" , config .MaxIdleConns , config .MaxIdleConnsPerHost )
654+ }
612655 if config .MaxHeaderBytes != 32768 || config .AuthMaxFailures != 7 {
613656 t .Fatalf ("header/auth limits = %d/%d, want 32768/7" , config .MaxHeaderBytes , config .AuthMaxFailures )
614657 }
@@ -692,6 +735,7 @@ func TestApplyEnvOverridesParsesDurations(t *testing.T) {
692735 {name : "TLS handshake" , envName : "PROXY_TLS_HANDSHAKE_TIMEOUT" , value : "11s" , get : func (c Config ) time.Duration { return time .Duration (c .TLSHandshakeTimeout ) }, want : 11 * time .Second },
693736 {name : "TLS reload" , envName : "PROXY_TLS_RELOAD_INTERVAL" , value : "45s" , get : func (c Config ) time.Duration { return time .Duration (c .TLSReloadInterval ) }, want : 45 * time .Second },
694737 {name : "response header" , envName : "PROXY_RESPONSE_HEADER_TIMEOUT" , value : "12s" , get : func (c Config ) time.Duration { return time .Duration (c .ResponseHeaderTimeout ) }, want : 12 * time .Second },
738+ {name : "idle connection" , envName : "PROXY_IDLE_CONN_TIMEOUT" , value : "75s" , get : func (c Config ) time.Duration { return time .Duration (c .IdleConnTimeout ) }, want : 75 * time .Second },
695739 {name : "read header" , envName : "PROXY_READ_HEADER_TIMEOUT" , value : "13s" , get : func (c Config ) time.Duration { return time .Duration (c .ReadHeaderTimeout ) }, want : 13 * time .Second },
696740 {name : "idle" , envName : "PROXY_IDLE_TIMEOUT" , value : "3m" , get : func (c Config ) time.Duration { return time .Duration (c .IdleTimeout ) }, want : 3 * time .Minute },
697741 {name : "tunnel idle" , envName : "PROXY_TUNNEL_IDLE_TIMEOUT" , value : "4m" , get : func (c Config ) time.Duration { return time .Duration (c .TunnelIdleTimeout ) }, want : 4 * time .Minute },
@@ -725,6 +769,7 @@ func TestApplyEnvOverridesRejectsInvalidDurations(t *testing.T) {
725769 {name : "TLS handshake" , envName : "PROXY_TLS_HANDSHAKE_TIMEOUT" },
726770 {name : "TLS reload" , envName : "PROXY_TLS_RELOAD_INTERVAL" },
727771 {name : "response header" , envName : "PROXY_RESPONSE_HEADER_TIMEOUT" },
772+ {name : "idle connection" , envName : "PROXY_IDLE_CONN_TIMEOUT" },
728773 {name : "read header" , envName : "PROXY_READ_HEADER_TIMEOUT" },
729774 {name : "idle" , envName : "PROXY_IDLE_TIMEOUT" },
730775 {name : "tunnel idle" , envName : "PROXY_TUNNEL_IDLE_TIMEOUT" },
@@ -766,6 +811,8 @@ func clearProxyEnvironment(t *testing.T) {
766811 "PROXY_MAX_CONNECTIONS_PER_IP" ,
767812 "PROXY_MAX_TUNNELS" ,
768813 "PROXY_MAX_TUNNELS_PER_IP" ,
814+ "PROXY_MAX_IDLE_CONNS" ,
815+ "PROXY_MAX_IDLE_CONNS_PER_HOST" ,
769816 "PROXY_MAX_HEADER_BYTES" ,
770817 "PROXY_AUTH_MAX_FAILURES" ,
771818 "PROXY_ALLOW_PRIVATE_DESTINATIONS" ,
@@ -774,6 +821,7 @@ func clearProxyEnvironment(t *testing.T) {
774821 "PROXY_TLS_HANDSHAKE_TIMEOUT" ,
775822 "PROXY_TLS_RELOAD_INTERVAL" ,
776823 "PROXY_RESPONSE_HEADER_TIMEOUT" ,
824+ "PROXY_IDLE_CONN_TIMEOUT" ,
777825 "PROXY_READ_HEADER_TIMEOUT" ,
778826 "PROXY_IDLE_TIMEOUT" ,
779827 "PROXY_TUNNEL_IDLE_TIMEOUT" ,
0 commit comments