@@ -382,6 +382,19 @@ func (tr *transportRequest) setError(err error) {
382
382
tr .mu .Unlock ()
383
383
}
384
384
385
+ // useRegisteredProtocol reports whether an alternate protocol (as reqistered
386
+ // with Transport.RegisterProtocol) should be respected for this request.
387
+ func (t * Transport ) useRegisteredProtocol (req * Request ) bool {
388
+ if req .URL .Scheme == "https" && req .requiresHTTP1 () {
389
+ // If this request requires HTTP/1, don't use the
390
+ // "https" alternate protocol, which is used by the
391
+ // HTTP/2 code to take over requests if there's an
392
+ // existing cached HTTP/2 connection.
393
+ return false
394
+ }
395
+ return true
396
+ }
397
+
385
398
// roundTrip implements a RoundTripper over HTTP.
386
399
func (t * Transport ) roundTrip (req * Request ) (* Response , error ) {
387
400
t .nextProtoOnce .Do (t .onceSetNextProtoDefaults )
@@ -411,10 +424,12 @@ func (t *Transport) roundTrip(req *Request) (*Response, error) {
411
424
}
412
425
}
413
426
414
- altProto , _ := t .altProto .Load ().(map [string ]RoundTripper )
415
- if altRT := altProto [scheme ]; altRT != nil {
416
- if resp , err := altRT .RoundTrip (req ); err != ErrSkipAltProtocol {
417
- return resp , err
427
+ if t .useRegisteredProtocol (req ) {
428
+ altProto , _ := t .altProto .Load ().(map [string ]RoundTripper )
429
+ if altRT := altProto [scheme ]; altRT != nil {
430
+ if resp , err := altRT .RoundTrip (req ); err != ErrSkipAltProtocol {
431
+ return resp , err
432
+ }
418
433
}
419
434
}
420
435
if ! isHTTP {
@@ -653,6 +668,7 @@ func (t *Transport) connectMethodForRequest(treq *transportRequest) (cm connectM
653
668
}
654
669
}
655
670
}
671
+ cm .onlyH1 = treq .requiresHTTP1 ()
656
672
return cm , err
657
673
}
658
674
@@ -1155,6 +1171,9 @@ func (pconn *persistConn) addTLS(name string, trace *httptrace.ClientTrace) erro
1155
1171
if cfg .ServerName == "" {
1156
1172
cfg .ServerName = name
1157
1173
}
1174
+ if pconn .cacheKey .onlyH1 {
1175
+ cfg .NextProtos = nil
1176
+ }
1158
1177
plainConn := pconn .conn
1159
1178
tlsConn := tls .Client (plainConn , cfg )
1160
1179
errc := make (chan error , 2 )
@@ -1361,10 +1380,11 @@ func (w persistConnWriter) Write(p []byte) (n int, err error) {
1361
1380
//
1362
1381
// A connect method may be of the following types:
1363
1382
//
1364
- // Cache key form Description
1365
- // ----------------- -------------------------
1383
+ // connectMethod. key().String() Description
1384
+ // ------------------------------ -------------------------
1366
1385
// |http|foo.com http directly to server, no proxy
1367
1386
// |https|foo.com https directly to server, no proxy
1387
+ // |https,h1|foo.com https directly to server w/o HTTP/2, no proxy
1368
1388
// http://proxy.com|https|foo.com http to proxy, then CONNECT to foo.com
1369
1389
// http://proxy.com|http http to proxy, http to anywhere after that
1370
1390
// socks5://proxy.com|http|foo.com socks5 to proxy, then http to foo.com
@@ -1379,6 +1399,7 @@ type connectMethod struct {
1379
1399
// then targetAddr is not included in the connect method key, because the socket can
1380
1400
// be reused for different targetAddr values.
1381
1401
targetAddr string
1402
+ onlyH1 bool // whether to disable HTTP/2 and force HTTP/1
1382
1403
}
1383
1404
1384
1405
func (cm * connectMethod ) key () connectMethodKey {
@@ -1394,6 +1415,7 @@ func (cm *connectMethod) key() connectMethodKey {
1394
1415
proxy : proxyStr ,
1395
1416
scheme : cm .targetScheme ,
1396
1417
addr : targetAddr ,
1418
+ onlyH1 : cm .onlyH1 ,
1397
1419
}
1398
1420
}
1399
1421
@@ -1428,11 +1450,16 @@ func (cm *connectMethod) tlsHost() string {
1428
1450
// a URL.
1429
1451
type connectMethodKey struct {
1430
1452
proxy , scheme , addr string
1453
+ onlyH1 bool
1431
1454
}
1432
1455
1433
1456
func (k connectMethodKey ) String () string {
1434
1457
// Only used by tests.
1435
- return fmt .Sprintf ("%s|%s|%s" , k .proxy , k .scheme , k .addr )
1458
+ var h1 string
1459
+ if k .onlyH1 {
1460
+ h1 = ",h1"
1461
+ }
1462
+ return fmt .Sprintf ("%s|%s%s|%s" , k .proxy , k .scheme , h1 , k .addr )
1436
1463
}
1437
1464
1438
1465
// persistConn wraps a connection, usually a persistent one
0 commit comments