Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 24d1c42

Browse files
committed
http2: add IdleConnTimeout to http2.Transport
Exposes an IdleConnTimeout on http2.Transport directly, rather than rely on configuring it through the underlying http1 transport. For golang/go#57893
1 parent 82780d6 commit 24d1c42

File tree

2 files changed

+76
-0
lines changed

2 files changed

+76
-0
lines changed

http2/transport.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,12 @@ type Transport struct {
146146
// waiting for their turn.
147147
StrictMaxConcurrentStreams bool
148148

149+
// IdleConnTimeout is the maximum amount of time an idle
150+
// (keep-alive) connection will remain idle before closing
151+
// itself.
152+
// Zero means no limit.
153+
IdleConnTimeout time.Duration
154+
149155
// ReadIdleTimeout is the timeout after which a health check using ping
150156
// frame will be carried out if no frame is received on the connection.
151157
// Note that a ping response will is considered a received frame, so if
@@ -3109,9 +3115,17 @@ func (rt noDialH2RoundTripper) RoundTrip(req *http.Request) (*http.Response, err
31093115
}
31103116

31113117
func (t *Transport) idleConnTimeout() time.Duration {
3118+
// to keep things backwards compatible, we use non-zero values of
3119+
// IdleConnTimeout, followed by using the IdleConnTimeout on the underlying
3120+
// http1 transport, followed by 0
3121+
if t.IdleConnTimeout != 0 {
3122+
return t.IdleConnTimeout
3123+
}
3124+
31123125
if t.t1 != nil {
31133126
return t.t1.IdleConnTimeout
31143127
}
3128+
31153129
return 0
31163130
}
31173131

http2/transport_test.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,68 @@ func startH2cServer(t *testing.T) net.Listener {
9595
return l
9696
}
9797

98+
func TestIdleConnTimeout(t *testing.T) {
99+
for _, test := range []struct {
100+
idleConnTimeout time.Duration
101+
wait time.Duration
102+
baseTransport *http.Transport
103+
wantConns int32
104+
}{{
105+
idleConnTimeout: 2 * time.Second,
106+
wait: 1 * time.Second,
107+
baseTransport: nil,
108+
wantConns: 1,
109+
}, {
110+
idleConnTimeout: 1 * time.Second,
111+
wait: 2 * time.Second,
112+
baseTransport: nil,
113+
wantConns: 5,
114+
}, {
115+
idleConnTimeout: 0 * time.Second,
116+
wait: 1 * time.Second,
117+
baseTransport: &http.Transport{
118+
IdleConnTimeout: 2 * time.Second,
119+
},
120+
wantConns: 1,
121+
}} {
122+
var gotConns int32
123+
124+
st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
125+
io.WriteString(w, r.RemoteAddr)
126+
}, optOnlyServer)
127+
defer st.Close()
128+
129+
tr := &Transport{
130+
IdleConnTimeout: test.idleConnTimeout,
131+
TLSClientConfig: tlsConfigInsecure,
132+
}
133+
defer tr.CloseIdleConnections()
134+
135+
for i := 0; i < 5; i++ {
136+
req, _ := http.NewRequest("GET", st.ts.URL, http.NoBody)
137+
trace := &httptrace.ClientTrace{
138+
GotConn: func(connInfo httptrace.GotConnInfo) {
139+
if !connInfo.Reused {
140+
atomic.AddInt32(&gotConns, 1)
141+
}
142+
},
143+
}
144+
req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace))
145+
146+
_, err := tr.RoundTrip(req)
147+
if err != nil {
148+
t.Fatalf("%v", err)
149+
}
150+
151+
<-time.After(test.wait)
152+
}
153+
154+
if gotConns != test.wantConns {
155+
t.Errorf("incorrect gotConns: %d != %d", gotConns, test.wantConns)
156+
}
157+
}
158+
}
159+
98160
func TestTransportH2c(t *testing.T) {
99161
l := startH2cServer(t)
100162
defer l.Close()

0 commit comments

Comments
 (0)