@@ -1489,6 +1489,98 @@ func TestTransportProxy(t *testing.T) {
1489
1489
}
1490
1490
}
1491
1491
1492
+ func TestOnProxyConnectResponse (t * testing.T ) {
1493
+
1494
+ var tcases = []struct {
1495
+ proxyStatusCode int
1496
+ err error
1497
+ }{
1498
+ {
1499
+ StatusOK ,
1500
+ nil ,
1501
+ },
1502
+ {
1503
+ StatusForbidden ,
1504
+ errors .New ("403" ),
1505
+ },
1506
+ }
1507
+ for _ , tcase := range tcases {
1508
+ h1 := HandlerFunc (func (w ResponseWriter , r * Request ) {
1509
+
1510
+ })
1511
+
1512
+ h2 := HandlerFunc (func (w ResponseWriter , r * Request ) {
1513
+ // Implement an entire CONNECT proxy
1514
+ if r .Method == "CONNECT" {
1515
+ if tcase .proxyStatusCode != StatusOK {
1516
+ w .WriteHeader (tcase .proxyStatusCode )
1517
+ return
1518
+ }
1519
+ hijacker , ok := w .(Hijacker )
1520
+ if ! ok {
1521
+ t .Errorf ("hijack not allowed" )
1522
+ return
1523
+ }
1524
+ clientConn , _ , err := hijacker .Hijack ()
1525
+ if err != nil {
1526
+ t .Errorf ("hijacking failed" )
1527
+ return
1528
+ }
1529
+ res := & Response {
1530
+ StatusCode : StatusOK ,
1531
+ Proto : "HTTP/1.1" ,
1532
+ ProtoMajor : 1 ,
1533
+ ProtoMinor : 1 ,
1534
+ Header : make (Header ),
1535
+ }
1536
+
1537
+ targetConn , err := net .Dial ("tcp" , r .URL .Host )
1538
+ if err != nil {
1539
+ t .Errorf ("net.Dial(%q) failed: %v" , r .URL .Host , err )
1540
+ return
1541
+ }
1542
+
1543
+ if err := res .Write (clientConn ); err != nil {
1544
+ t .Errorf ("Writing 200 OK failed: %v" , err )
1545
+ return
1546
+ }
1547
+
1548
+ go io .Copy (targetConn , clientConn )
1549
+ go func () {
1550
+ io .Copy (clientConn , targetConn )
1551
+ targetConn .Close ()
1552
+ }()
1553
+ }
1554
+ })
1555
+ ts := newClientServerTest (t , https1Mode , h1 ).ts
1556
+ proxy := newClientServerTest (t , https1Mode , h2 ).ts
1557
+
1558
+ pu , err := url .Parse (proxy .URL )
1559
+ if err != nil {
1560
+ t .Fatal (err )
1561
+ }
1562
+
1563
+ c := proxy .Client ()
1564
+
1565
+ c .Transport .(* Transport ).Proxy = ProxyURL (pu )
1566
+ c .Transport .(* Transport ).OnProxyConnectResponse = func (ctx context.Context , proxyURL * url.URL , connectReq * Request , connectRes * Response ) error {
1567
+ if proxyURL .String () != pu .String () {
1568
+ t .Errorf ("proxy url got %s, want %s" , proxyURL , pu )
1569
+ }
1570
+
1571
+ if "https://" + connectReq .URL .String () != ts .URL {
1572
+ t .Errorf ("connect url got %s, want %s" , connectReq .URL , ts .URL )
1573
+ }
1574
+ return tcase .err
1575
+ }
1576
+ if _ , err := c .Head (ts .URL ); err != nil {
1577
+ if tcase .err != nil && ! strings .Contains (err .Error (), tcase .err .Error ()) {
1578
+ t .Errorf ("got %v, want %v" , err , tcase .err )
1579
+ }
1580
+ }
1581
+ }
1582
+ }
1583
+
1492
1584
// Issue 28012: verify that the Transport closes its TCP connection to http proxies
1493
1585
// when they're slow to reply to HTTPS CONNECT responses.
1494
1586
func TestTransportProxyHTTPSConnectLeak (t * testing.T ) {
@@ -5903,7 +5995,10 @@ func TestTransportRequestWriteRoundTrip(t *testing.T) {
5903
5995
5904
5996
func TestTransportClone (t * testing.T ) {
5905
5997
tr := & Transport {
5906
- Proxy : func (* Request ) (* url.URL , error ) { panic ("" ) },
5998
+ Proxy : func (* Request ) (* url.URL , error ) { panic ("" ) },
5999
+ OnProxyConnectResponse : func (ctx context.Context , proxyURL * url.URL , connectReq * Request , connectRes * Response ) error {
6000
+ return nil
6001
+ },
5907
6002
DialContext : func (ctx context.Context , network , addr string ) (net.Conn , error ) { panic ("" ) },
5908
6003
Dial : func (network , addr string ) (net.Conn , error ) { panic ("" ) },
5909
6004
DialTLS : func (network , addr string ) (net.Conn , error ) { panic ("" ) },
0 commit comments