diff options
Diffstat (limited to 'src/net/http')
| -rw-r--r-- | src/net/http/http.go | 15 | ||||
| -rw-r--r-- | src/net/http/transport_dial_test.go | 39 |
2 files changed, 52 insertions, 2 deletions
diff --git a/src/net/http/http.go b/src/net/http/http.go index 0f9165bf03..e7959fa3b6 100644 --- a/src/net/http/http.go +++ b/src/net/http/http.go @@ -235,10 +235,23 @@ type Pusher interface { // both [Transport] and [Server]. type HTTP2Config struct { // MaxConcurrentStreams optionally specifies the number of - // concurrent streams that a peer may have open at a time. + // concurrent streams that a client may have open at a time. // If zero, MaxConcurrentStreams defaults to at least 100. + // + // This parameter only applies to Servers. MaxConcurrentStreams int + // StrictMaxConcurrentRequests controls whether an HTTP/2 server's + // concurrency limit should be respected across all connections + // to that server. + // If true, new requests sent when a connection's concurrency limit + // has been exceeded will block until an existing request completes. + // If false, an additional connection will be opened if all + // existing connections are at their limit. + // + // This parameter only applies to Transports. + StrictMaxConcurrentRequests bool + // MaxDecoderHeaderTableSize optionally specifies an upper limit for the // size of the header compression table used for decoding headers sent // by the peer. diff --git a/src/net/http/transport_dial_test.go b/src/net/http/transport_dial_test.go index d7f7a3d539..086039ece9 100644 --- a/src/net/http/transport_dial_test.go +++ b/src/net/http/transport_dial_test.go @@ -59,7 +59,7 @@ func TestTransportPoolConnCannotReuseConnectionInUse(t *testing.T) { // When an HTTP/2 connection is at its stream limit // a new request is made on a new connection. -func TestTransportPoolConnHTTP2OverStreamLimit(t *testing.T) { +func testTransportPoolConnHTTP2NoStrictMaxConcurrentRequests(t *testing.T) { synctest.Test(t, func(t *testing.T) { dt := newTransportDialTester(t, http2Mode, func(srv *http.Server) { srv.HTTP2 = &http.HTTP2Config{ @@ -100,6 +100,43 @@ func TestTransportPoolConnHTTP2OverStreamLimit(t *testing.T) { }) } +// When an HTTP/2 connection is at its stream limit +// and StrictMaxConcurrentRequests = true, +// a new request waits for a slot on the existing connection. +func TestTransportPoolConnHTTP2StrictMaxConcurrentRequests(t *testing.T) { + t.Skip("skipped until h2_bundle.go includes support for StrictMaxConcurrentRequests") + + synctest.Test(t, func(t *testing.T) { + dt := newTransportDialTester(t, http2Mode, func(srv *http.Server) { + srv.HTTP2.MaxConcurrentStreams = 2 + }, func(tr *http.Transport) { + tr.HTTP2 = &http.HTTP2Config{ + StrictMaxConcurrentRequests: true, + } + }) + + // First request dials an HTTP/2 connection. + rt1 := dt.roundTrip() + c1 := dt.wantDial() + c1.finish(nil) + rt1.wantDone(c1, "HTTP/2.0") + + // Second request uses the existing connection. + rt2 := dt.roundTrip() + rt2.wantDone(c1, "HTTP/2.0") + + // Third request blocks waiting for a slot on the existing connection. + rt3 := dt.roundTrip() + + // First request finishing unblocks the thirrd. + rt1.finish() + rt3.wantDone(c1, "HTTP/2.0") + + rt2.finish() + rt3.finish() + }) +} + // A new request made while an HTTP/2 dial is in progress will start a second dial. func TestTransportPoolConnHTTP2Startup(t *testing.T) { synctest.Test(t, func(t *testing.T) { |
