Source file
src/net/http/transport.go
1
2
3
4
5
6
7
8
9
10 package http
11
12 import (
13 "bufio"
14 "compress/flate"
15 "compress/gzip"
16 "container/list"
17 "context"
18 "crypto/tls"
19 "errors"
20 "fmt"
21 "internal/godebug"
22 "io"
23 "log"
24 "maps"
25 "net"
26 "net/http/httptrace"
27 "net/http/internal"
28 "net/http/internal/ascii"
29 "net/textproto"
30 "net/url"
31 "reflect"
32 "strings"
33 "sync"
34 "sync/atomic"
35 "time"
36 _ "unsafe"
37
38 "golang.org/x/net/http/httpguts"
39 "golang.org/x/net/http/httpproxy"
40 )
41
42
43
44
45
46
47
48 var DefaultTransport RoundTripper = &Transport{
49 Proxy: ProxyFromEnvironment,
50 DialContext: defaultTransportDialContext(&net.Dialer{
51 Timeout: 30 * time.Second,
52 KeepAlive: 30 * time.Second,
53 }),
54 ForceAttemptHTTP2: true,
55 MaxIdleConns: 100,
56 IdleConnTimeout: 90 * time.Second,
57 TLSHandshakeTimeout: 10 * time.Second,
58 ExpectContinueTimeout: 1 * time.Second,
59 }
60
61
62
63 const DefaultMaxIdleConnsPerHost = 2
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99 type Transport struct {
100 idleMu sync.Mutex
101 closeIdle bool
102 idleConn map[connectMethodKey][]*persistConn
103 idleConnWait map[connectMethodKey]wantConnQueue
104 idleLRU connLRU
105
106 reqMu sync.Mutex
107 reqCanceler map[*Request]context.CancelCauseFunc
108
109 altMu sync.Mutex
110 altProto atomic.Value
111
112 connsPerHostMu sync.Mutex
113 connsPerHost map[connectMethodKey]int
114 connsPerHostWait map[connectMethodKey]wantConnQueue
115 dialsInProgress wantConnQueue
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131 Proxy func(*Request) (*url.URL, error)
132
133
134
135
136 OnProxyConnectResponse func(ctx context.Context, proxyURL *url.URL, connectReq *Request, connectRes *Response) error
137
138
139
140
141
142
143
144
145
146 DialContext func(ctx context.Context, network, addr string) (net.Conn, error)
147
148
149
150
151
152
153
154
155
156
157
158 Dial func(network, addr string) (net.Conn, error)
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173 DialTLSContext func(ctx context.Context, network, addr string) (net.Conn, error)
174
175
176
177
178
179
180
181 DialTLS func(network, addr string) (net.Conn, error)
182
183
184
185
186
187 TLSClientConfig *tls.Config
188
189
190
191 TLSHandshakeTimeout time.Duration
192
193
194
195
196
197
198 DisableKeepAlives bool
199
200
201
202
203
204
205
206
207
208 DisableCompression bool
209
210
211
212 MaxIdleConns int
213
214
215
216
217 MaxIdleConnsPerHost int
218
219
220
221
222
223
224 MaxConnsPerHost int
225
226
227
228
229
230 IdleConnTimeout time.Duration
231
232
233
234
235
236 ResponseHeaderTimeout time.Duration
237
238
239
240
241
242
243
244
245 ExpectContinueTimeout time.Duration
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260 TLSNextProto map[string]func(authority string, c *tls.Conn) RoundTripper
261
262
263
264
265 ProxyConnectHeader Header
266
267
268
269
270
271
272
273
274 GetProxyConnectHeader func(ctx context.Context, proxyURL *url.URL, target string) (Header, error)
275
276
277
278
279
280
281 MaxResponseHeaderBytes int64
282
283
284
285
286 WriteBufferSize int
287
288
289
290
291 ReadBufferSize int
292
293
294
295 nextProtoOnce sync.Once
296 closeIdleFunc closeIdleConnectionser
297 h2Transport *http2Transport
298 h2Config http2ExternalTransportConfig
299 h3Transport dialClientConner
300 tlsNextProtoWasNil bool
301
302
303
304
305
306
307 ForceAttemptHTTP2 bool
308
309
310 HTTP2 *HTTP2Config
311
312
313
314
315
316
317
318
319
320 Protocols *Protocols
321 }
322
323 func (t *Transport) writeBufferSize() int {
324 if t.WriteBufferSize > 0 {
325 return t.WriteBufferSize
326 }
327 return 4 << 10
328 }
329
330 func (t *Transport) readBufferSize() int {
331 if t.ReadBufferSize > 0 {
332 return t.ReadBufferSize
333 }
334 return 4 << 10
335 }
336
337 func (t *Transport) maxHeaderResponseSize() int64 {
338 if t.MaxResponseHeaderBytes > 0 {
339 return t.MaxResponseHeaderBytes
340 }
341 return 10 << 20
342 }
343
344
345 func (t *Transport) Clone() *Transport {
346 t.nextProtoOnce.Do(t.onceSetNextProtoDefaults)
347 t2 := &Transport{
348 Proxy: t.Proxy,
349 OnProxyConnectResponse: t.OnProxyConnectResponse,
350 DialContext: t.DialContext,
351 Dial: t.Dial,
352 DialTLS: t.DialTLS,
353 DialTLSContext: t.DialTLSContext,
354 TLSHandshakeTimeout: t.TLSHandshakeTimeout,
355 DisableKeepAlives: t.DisableKeepAlives,
356 DisableCompression: t.DisableCompression,
357 MaxIdleConns: t.MaxIdleConns,
358 MaxIdleConnsPerHost: t.MaxIdleConnsPerHost,
359 MaxConnsPerHost: t.MaxConnsPerHost,
360 IdleConnTimeout: t.IdleConnTimeout,
361 ResponseHeaderTimeout: t.ResponseHeaderTimeout,
362 ExpectContinueTimeout: t.ExpectContinueTimeout,
363 ProxyConnectHeader: t.ProxyConnectHeader.Clone(),
364 GetProxyConnectHeader: t.GetProxyConnectHeader,
365 MaxResponseHeaderBytes: t.MaxResponseHeaderBytes,
366 ForceAttemptHTTP2: t.ForceAttemptHTTP2,
367 WriteBufferSize: t.WriteBufferSize,
368 ReadBufferSize: t.ReadBufferSize,
369 }
370 if t.TLSClientConfig != nil {
371 t2.TLSClientConfig = t.TLSClientConfig.Clone()
372 }
373 if t.HTTP2 != nil {
374 t2.HTTP2 = &HTTP2Config{}
375 *t2.HTTP2 = *t.HTTP2
376 }
377 if t.Protocols != nil {
378 t2.Protocols = &Protocols{}
379 *t2.Protocols = *t.Protocols
380 }
381 if !t.tlsNextProtoWasNil {
382 npm := maps.Clone(t.TLSNextProto)
383 if npm == nil {
384 npm = make(map[string]func(authority string, c *tls.Conn) RoundTripper)
385 }
386 t2.TLSNextProto = npm
387 }
388 return t2
389 }
390
391 type dialClientConner interface {
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417 DialClientConn(ctx context.Context, address string, proxy *url.URL, tlsConfig *tls.Config, internalStateHook func()) (RoundTripper, error)
418 }
419
420 type closeIdleConnectionser interface {
421
422
423
424
425
426
427
428
429 CloseIdleConnections()
430 }
431
432 func (t *Transport) hasCustomTLSDialer() bool {
433 return t.DialTLS != nil || t.DialTLSContext != nil
434 }
435
436 var http2client = godebug.New("http2client")
437
438
439
440 func (t *Transport) onceSetNextProtoDefaults() {
441 t.tlsNextProtoWasNil = (t.TLSNextProto == nil)
442 if http2client.Value() == "0" {
443 http2client.IncNonDefault()
444 return
445 }
446
447
448
449
450
451
452 altProto, _ := t.altProto.Load().(map[string]RoundTripper)
453 if rv := reflect.ValueOf(altProto["https"]); rv.IsValid() && rv.Type().Kind() == reflect.Struct && rv.Type().NumField() == 1 {
454 if v := rv.Field(0); v.CanInterface() {
455 if h2i, ok := v.Interface().(closeIdleConnectionser); ok {
456 t.closeIdleFunc = h2i
457 return
458 }
459 }
460 }
461
462 if _, ok := t.TLSNextProto["h2"]; ok {
463
464 return
465 }
466 protocols := t.protocols()
467 if !protocols.HTTP2() && !protocols.UnencryptedHTTP2() {
468 return
469 }
470 if omitBundledHTTP2 {
471 return
472 }
473
474 t.configureHTTP2(protocols)
475 }
476
477 func (t *Transport) protocols() Protocols {
478 if t.Protocols != nil {
479 return *t.Protocols
480 }
481 var p Protocols
482 p.SetHTTP1(true)
483 switch {
484 case t.TLSNextProto != nil:
485
486
487 if t.TLSNextProto["h2"] != nil {
488 p.SetHTTP2(true)
489 }
490 case !t.ForceAttemptHTTP2 && (t.TLSClientConfig != nil || t.Dial != nil || t.DialContext != nil || t.hasCustomTLSDialer()):
491
492
493
494
495
496
497 case http2client.Value() == "0":
498 default:
499 p.SetHTTP2(true)
500 }
501 return p
502 }
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521 func ProxyFromEnvironment(req *Request) (*url.URL, error) {
522 return envProxyFunc()(req.URL)
523 }
524
525
526
527 func ProxyURL(fixedURL *url.URL) func(*Request) (*url.URL, error) {
528 return func(*Request) (*url.URL, error) {
529 return fixedURL, nil
530 }
531 }
532
533
534
535
536 type transportRequest struct {
537 *Request
538 extra Header
539 trace *httptrace.ClientTrace
540
541 ctx context.Context
542 cancel context.CancelCauseFunc
543
544 mu sync.Mutex
545 err error
546 }
547
548 func (tr *transportRequest) extraHeaders() Header {
549 if tr.extra == nil {
550 tr.extra = make(Header)
551 }
552 return tr.extra
553 }
554
555 func (tr *transportRequest) setError(err error) {
556 tr.mu.Lock()
557 if tr.err == nil {
558 tr.err = err
559 }
560 tr.mu.Unlock()
561 }
562
563
564
565 func (t *Transport) useRegisteredProtocol(req *Request) bool {
566 if req.URL.Scheme == "https" && req.requiresHTTP1() {
567
568
569
570
571 return false
572 }
573 return true
574 }
575
576
577
578
579 func (t *Transport) alternateRoundTripper(req *Request) RoundTripper {
580 if !t.useRegisteredProtocol(req) {
581 return nil
582 }
583 if req.URL.Scheme == "https" && t.h2Config != nil && t.h2Config.ExternalRoundTrip() {
584
585
586
587
588
589
590 return t.h2Config
591 }
592 altProto, _ := t.altProto.Load().(map[string]RoundTripper)
593 return altProto[req.URL.Scheme]
594 }
595
596 func validateHeaders(hdrs Header) string {
597 for k, vv := range hdrs {
598 if !httpguts.ValidHeaderFieldName(k) {
599 return fmt.Sprintf("field name %q", k)
600 }
601 for _, v := range vv {
602 if !httpguts.ValidHeaderFieldValue(v) {
603
604
605 return fmt.Sprintf("field value for %q", k)
606 }
607 }
608 }
609 return ""
610 }
611
612
613 func (t *Transport) roundTrip(req *Request) (_ *Response, err error) {
614 t.nextProtoOnce.Do(t.onceSetNextProtoDefaults)
615 ctx := req.Context()
616 trace := httptrace.ContextClientTrace(ctx)
617
618 if req.URL == nil {
619 req.closeBody()
620 return nil, errors.New("http: nil Request.URL")
621 }
622 if req.Header == nil {
623 req.closeBody()
624 return nil, errors.New("http: nil Request.Header")
625 }
626 scheme := req.URL.Scheme
627 isHTTP := scheme == "http" || scheme == "https"
628 if isHTTP {
629
630 if err := validateHeaders(req.Header); err != "" {
631 req.closeBody()
632 return nil, fmt.Errorf("net/http: invalid header %s", err)
633 }
634
635
636 if err := validateHeaders(req.Trailer); err != "" {
637 req.closeBody()
638 return nil, fmt.Errorf("net/http: invalid trailer %s", err)
639 }
640 }
641
642 origReq := req
643 req = setupRewindBody(req)
644
645 if altRT := t.alternateRoundTripper(req); altRT != nil {
646 if resp, err := altRT.RoundTrip(req); err != ErrSkipAltProtocol {
647 return resp, err
648 }
649 var err error
650 req, err = rewindBody(req)
651 if err != nil {
652 return nil, err
653 }
654 }
655 if !isHTTP {
656 req.closeBody()
657 return nil, badStringError("unsupported protocol scheme", scheme)
658 }
659 if req.Method != "" && !validMethod(req.Method) {
660 req.closeBody()
661 return nil, fmt.Errorf("net/http: invalid method %q", req.Method)
662 }
663 if req.URL.Host == "" {
664 req.closeBody()
665 return nil, errors.New("http: no Host in request URL")
666 }
667
668
669
670
671
672
673
674
675
676
677 ctx, cancel := context.WithCancelCause(req.Context())
678
679
680 if origReq.Cancel != nil {
681 go awaitLegacyCancel(ctx, cancel, origReq)
682 }
683
684
685
686
687
688 cancel = t.prepareTransportCancel(origReq, cancel)
689
690 defer func() {
691 if err != nil {
692 cancel(err)
693 }
694 }()
695
696 for {
697 select {
698 case <-ctx.Done():
699 req.closeBody()
700 return nil, context.Cause(ctx)
701 default:
702 }
703
704
705 treq := &transportRequest{Request: req, trace: trace, ctx: ctx, cancel: cancel}
706 cm, err := t.connectMethodForRequest(treq)
707 if err != nil {
708 req.closeBody()
709 return nil, err
710 }
711
712
713
714
715
716 pconn, err := t.getConn(treq, cm)
717 if err != nil {
718 req.closeBody()
719 return nil, err
720 }
721
722 var resp *Response
723 if pconn.alt != nil {
724
725 resp, err = pconn.alt.RoundTrip(req)
726 } else {
727 resp, err = pconn.roundTrip(treq)
728 }
729 if err == nil {
730 if pconn.alt != nil {
731
732
733
734
735
736 cancel(errRequestDone)
737 }
738 resp.Request = origReq
739 return resp, nil
740 }
741
742
743 if http2isNoCachedConnError(err) {
744 if t.removeIdleConn(pconn) {
745 t.decConnsPerHost(pconn.cacheKey)
746 }
747 } else if !pconn.shouldRetryRequest(req, err) {
748
749
750 if e, ok := err.(nothingWrittenError); ok {
751 err = e.error
752 }
753 if e, ok := err.(transportReadFromServerError); ok {
754 err = e.err
755 }
756 if b, ok := req.Body.(*readTrackingBody); ok && !b.didClose.Load() {
757
758
759
760 req.closeBody()
761 }
762 return nil, err
763 }
764 testHookRoundTripRetried()
765
766
767 req, err = rewindBody(req)
768 if err != nil {
769 return nil, err
770 }
771 }
772 }
773
774 func http2isNoCachedConnError(err error) bool {
775 _, ok := err.(interface{ IsHTTP2NoCachedConnError() })
776 return ok
777 }
778
779 func awaitLegacyCancel(ctx context.Context, cancel context.CancelCauseFunc, req *Request) {
780 select {
781 case <-req.Cancel:
782 cancel(errRequestCanceled)
783 case <-ctx.Done():
784 }
785 }
786
787 var errCannotRewind = errors.New("net/http: cannot rewind body after connection loss")
788
789 type readTrackingBody struct {
790 io.ReadCloser
791 didRead bool
792 didClose atomic.Bool
793 }
794
795 func (r *readTrackingBody) Read(data []byte) (int, error) {
796 r.didRead = true
797 return r.ReadCloser.Read(data)
798 }
799
800 func (r *readTrackingBody) Close() error {
801 if !r.didClose.CompareAndSwap(false, true) {
802 return nil
803 }
804 return r.ReadCloser.Close()
805 }
806
807
808
809
810
811 func setupRewindBody(req *Request) *Request {
812 if req.Body == nil || req.Body == NoBody {
813 return req
814 }
815 newReq := *req
816 newReq.Body = &readTrackingBody{ReadCloser: req.Body}
817 return &newReq
818 }
819
820
821
822
823
824 func rewindBody(req *Request) (rewound *Request, err error) {
825 if req.Body == nil || req.Body == NoBody || (!req.Body.(*readTrackingBody).didRead && !req.Body.(*readTrackingBody).didClose.Load()) {
826 return req, nil
827 }
828 if !req.Body.(*readTrackingBody).didClose.Load() {
829 req.closeBody()
830 }
831 if req.GetBody == nil {
832 return nil, errCannotRewind
833 }
834 body, err := req.GetBody()
835 if err != nil {
836 return nil, err
837 }
838 newReq := *req
839 newReq.Body = &readTrackingBody{ReadCloser: body}
840 return &newReq, nil
841 }
842
843
844
845
846 func (pc *persistConn) shouldRetryRequest(req *Request, err error) bool {
847 if http2isNoCachedConnError(err) {
848
849
850
851
852
853
854 return true
855 }
856 if err == errMissingHost {
857
858 return false
859 }
860 if !pc.isReused() {
861
862
863
864
865
866
867
868 return false
869 }
870 if _, ok := err.(nothingWrittenError); ok {
871
872
873 return req.outgoingLength() == 0 || req.GetBody != nil
874 }
875 if !req.isReplayable() {
876
877 return false
878 }
879 if _, ok := err.(transportReadFromServerError); ok {
880
881
882 return true
883 }
884 if err == errServerClosedIdle {
885
886
887
888 return true
889 }
890 return false
891 }
892
893
894 var ErrSkipAltProtocol = internal.ErrSkipAltProtocol
895
896
897
898
899
900
901
902
903
904
905
906 func (t *Transport) RegisterProtocol(scheme string, rt RoundTripper) {
907 if err := t.registerProtocol(scheme, rt); err != nil {
908 panic(err)
909 }
910 }
911
912 func (t *Transport) registerProtocol(scheme string, rt RoundTripper) error {
913 t.altMu.Lock()
914 defer t.altMu.Unlock()
915
916 if scheme == "http/2" {
917 if t.h2Config != nil {
918 panic("http: HTTP/2 Transport already registered")
919 }
920 var ok bool
921 if t.h2Config, ok = rt.(http2ExternalTransportConfig); !ok {
922 panic("http: HTTP/2 configuration does not implement ExternalTransportConfig")
923 }
924 t.h2Config.Registered(t)
925 }
926
927 if scheme == "http/3" {
928 if t.h3Transport != nil {
929 panic("http: HTTP/3 Transport already registered")
930 }
931 var ok bool
932 if t.h3Transport, ok = rt.(dialClientConner); !ok {
933 panic("http: HTTP/3 RoundTripper does not implement DialClientConn")
934 }
935
936
937 if r, ok := rt.(interface {
938 Registered(*Transport)
939 }); ok {
940 r.Registered(t)
941 }
942 return nil
943 }
944
945 oldMap, _ := t.altProto.Load().(map[string]RoundTripper)
946 if _, exists := oldMap[scheme]; exists {
947 return errors.New("protocol " + scheme + " already registered")
948 }
949 newMap := maps.Clone(oldMap)
950 if newMap == nil {
951 newMap = make(map[string]RoundTripper)
952 }
953 newMap[scheme] = rt
954 t.altProto.Store(newMap)
955 return nil
956 }
957
958
959
960
961
962 func (t *Transport) CloseIdleConnections() {
963 t.nextProtoOnce.Do(t.onceSetNextProtoDefaults)
964 t.idleMu.Lock()
965 m := t.idleConn
966 t.idleConn = nil
967 t.closeIdle = true
968 t.idleLRU = connLRU{}
969 t.idleMu.Unlock()
970 for _, conns := range m {
971 for _, pconn := range conns {
972 pconn.close(errCloseIdleConns)
973 }
974 }
975 t.connsPerHostMu.Lock()
976 t.dialsInProgress.all(func(w *wantConn) {
977 if w.cancelCtx != nil && !w.waiting() {
978 w.cancelCtx()
979 }
980 })
981 t.connsPerHostMu.Unlock()
982
983
984
985
986 if tr2 := t.h2Transport; tr2 != nil {
987 tr2.CloseIdleConnections()
988 }
989
990
991
992
993 if t2 := t.closeIdleFunc; t2 != nil {
994 t2.CloseIdleConnections()
995 }
996
997 if cc, ok := t.h3Transport.(closeIdleConnectionser); ok {
998 cc.CloseIdleConnections()
999 }
1000 }
1001
1002
1003 func (t *Transport) prepareTransportCancel(req *Request, origCancel context.CancelCauseFunc) context.CancelCauseFunc {
1004
1005
1006
1007
1008
1009
1010 cancel := func(err error) {
1011 origCancel(err)
1012 t.reqMu.Lock()
1013 delete(t.reqCanceler, req)
1014 t.reqMu.Unlock()
1015 }
1016 t.reqMu.Lock()
1017 if t.reqCanceler == nil {
1018 t.reqCanceler = make(map[*Request]context.CancelCauseFunc)
1019 }
1020 t.reqCanceler[req] = cancel
1021 t.reqMu.Unlock()
1022 return cancel
1023 }
1024
1025
1026
1027
1028
1029
1030
1031 func (t *Transport) CancelRequest(req *Request) {
1032 t.reqMu.Lock()
1033 cancel := t.reqCanceler[req]
1034 t.reqMu.Unlock()
1035 if cancel != nil {
1036 cancel(errRequestCanceled)
1037 }
1038 }
1039
1040
1041
1042
1043
1044 var (
1045 envProxyOnce sync.Once
1046 envProxyFuncValue func(*url.URL) (*url.URL, error)
1047 )
1048
1049
1050
1051 func envProxyFunc() func(*url.URL) (*url.URL, error) {
1052 envProxyOnce.Do(func() {
1053 envProxyFuncValue = httpproxy.FromEnvironment().ProxyFunc()
1054 })
1055 return envProxyFuncValue
1056 }
1057
1058
1059 func resetProxyConfig() {
1060 envProxyOnce = sync.Once{}
1061 envProxyFuncValue = nil
1062 }
1063
1064 func (t *Transport) connectMethodForRequest(treq *transportRequest) (cm connectMethod, err error) {
1065 cm.targetScheme = treq.URL.Scheme
1066 cm.targetAddr = canonicalAddr(treq.URL)
1067 if t.Proxy != nil {
1068 cm.proxyURL, err = t.Proxy(treq.Request)
1069 }
1070 cm.onlyH1 = treq.requiresHTTP1()
1071 return cm, err
1072 }
1073
1074
1075
1076 func (cm *connectMethod) proxyAuth() string {
1077 if cm.proxyURL == nil {
1078 return ""
1079 }
1080 if u := cm.proxyURL.User; u != nil {
1081 username := u.Username()
1082 password, _ := u.Password()
1083 return "Basic " + basicAuth(username, password)
1084 }
1085 return ""
1086 }
1087
1088
1089 var (
1090 errKeepAlivesDisabled = errors.New("http: putIdleConn: keep alives disabled")
1091 errConnBroken = errors.New("http: putIdleConn: connection is in bad state")
1092 errCloseIdle = errors.New("http: putIdleConn: CloseIdleConnections was called")
1093 errTooManyIdle = errors.New("http: putIdleConn: too many idle connections")
1094 errTooManyIdleHost = errors.New("http: putIdleConn: too many idle connections for host")
1095 errCloseIdleConns = errors.New("http: CloseIdleConnections called")
1096 errReadLoopExiting = errors.New("http: persistConn.readLoop exiting")
1097 errIdleConnTimeout = errors.New("http: idle connection timeout")
1098
1099
1100
1101
1102
1103 errServerClosedIdle = errors.New("http: server closed idle connection")
1104 )
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114 type transportReadFromServerError struct {
1115 err error
1116 }
1117
1118 func (e transportReadFromServerError) Unwrap() error { return e.err }
1119
1120 func (e transportReadFromServerError) Error() string {
1121 return fmt.Sprintf("net/http: Transport failed to read from server: %v", e.err)
1122 }
1123
1124 func (t *Transport) putOrCloseIdleConn(pconn *persistConn) {
1125 if err := t.tryPutIdleConn(pconn); err != nil {
1126 pconn.close(err)
1127 }
1128 }
1129
1130 func (t *Transport) maxIdleConnsPerHost() int {
1131 if v := t.MaxIdleConnsPerHost; v != 0 {
1132 return v
1133 }
1134 return DefaultMaxIdleConnsPerHost
1135 }
1136
1137
1138
1139
1140
1141
1142 func (t *Transport) tryPutIdleConn(pconn *persistConn) error {
1143 if t.DisableKeepAlives || t.MaxIdleConnsPerHost < 0 {
1144 return errKeepAlivesDisabled
1145 }
1146 if pconn.isBroken() {
1147 return errConnBroken
1148 }
1149 pconn.markReused()
1150 if pconn.isClientConn {
1151
1152 defer pconn.internalStateHook()
1153 pconn.mu.Lock()
1154 defer pconn.mu.Unlock()
1155 if !pconn.inFlight {
1156 panic("pconn is not in flight")
1157 }
1158 pconn.inFlight = false
1159 select {
1160 case pconn.availch <- struct{}{}:
1161 default:
1162 panic("unable to make pconn available")
1163 }
1164 return nil
1165 }
1166
1167 t.idleMu.Lock()
1168 defer t.idleMu.Unlock()
1169
1170
1171
1172
1173 if pconn.alt != nil && t.idleLRU.m[pconn] != nil {
1174 return nil
1175 }
1176
1177
1178
1179
1180
1181 key := pconn.cacheKey
1182 if q, ok := t.idleConnWait[key]; ok {
1183 done := false
1184 if pconn.alt == nil {
1185
1186
1187 for q.len() > 0 {
1188 w := q.popFront()
1189 if w.tryDeliver(pconn, nil, time.Time{}) {
1190 done = true
1191 break
1192 }
1193 }
1194 } else {
1195
1196
1197
1198
1199 for q.len() > 0 {
1200 w := q.popFront()
1201 w.tryDeliver(pconn, nil, time.Time{})
1202 }
1203 }
1204 if q.len() == 0 {
1205 delete(t.idleConnWait, key)
1206 } else {
1207 t.idleConnWait[key] = q
1208 }
1209 if done {
1210 return nil
1211 }
1212 }
1213
1214 if t.closeIdle {
1215 return errCloseIdle
1216 }
1217 if t.idleConn == nil {
1218 t.idleConn = make(map[connectMethodKey][]*persistConn)
1219 }
1220 idles := t.idleConn[key]
1221 if len(idles) >= t.maxIdleConnsPerHost() {
1222 return errTooManyIdleHost
1223 }
1224 for _, exist := range idles {
1225 if exist == pconn {
1226 log.Fatalf("dup idle pconn %p in freelist", pconn)
1227 }
1228 }
1229 t.idleConn[key] = append(idles, pconn)
1230 t.idleLRU.add(pconn)
1231 if t.MaxIdleConns != 0 && t.idleLRU.len() > t.MaxIdleConns {
1232 oldest := t.idleLRU.removeOldest()
1233 oldest.close(errTooManyIdle)
1234 t.removeIdleConnLocked(oldest)
1235 }
1236
1237
1238
1239
1240 if t.IdleConnTimeout > 0 && pconn.alt == nil {
1241 if pconn.idleTimer != nil {
1242 pconn.idleTimer.Reset(t.IdleConnTimeout)
1243 } else {
1244 pconn.idleTimer = time.AfterFunc(t.IdleConnTimeout, pconn.closeConnIfStillIdle)
1245 }
1246 }
1247 pconn.idleAt = time.Now()
1248 return nil
1249 }
1250
1251
1252
1253
1254 func (t *Transport) queueForIdleConn(w *wantConn) (delivered bool) {
1255 if t.DisableKeepAlives {
1256 return false
1257 }
1258
1259 t.idleMu.Lock()
1260 defer t.idleMu.Unlock()
1261
1262
1263
1264 t.closeIdle = false
1265
1266 if w == nil {
1267
1268 return false
1269 }
1270
1271
1272
1273
1274 var oldTime time.Time
1275 if t.IdleConnTimeout > 0 {
1276 oldTime = time.Now().Add(-t.IdleConnTimeout)
1277 }
1278
1279
1280 if list, ok := t.idleConn[w.key]; ok {
1281 stop := false
1282 delivered := false
1283 for len(list) > 0 && !stop {
1284 pconn := list[len(list)-1]
1285
1286
1287
1288
1289 tooOld := !oldTime.IsZero() && pconn.idleAt.Round(0).Before(oldTime)
1290 if tooOld {
1291
1292
1293
1294 go pconn.closeConnIfStillIdle()
1295 }
1296 if pconn.isBroken() || tooOld {
1297
1298
1299
1300
1301
1302 list = list[:len(list)-1]
1303 continue
1304 }
1305 delivered = w.tryDeliver(pconn, nil, pconn.idleAt)
1306 if delivered {
1307 if pconn.alt != nil {
1308
1309
1310 } else {
1311
1312
1313 t.idleLRU.remove(pconn)
1314 list = list[:len(list)-1]
1315 }
1316 }
1317 stop = true
1318 }
1319 if len(list) > 0 {
1320 t.idleConn[w.key] = list
1321 } else {
1322 delete(t.idleConn, w.key)
1323 }
1324 if stop {
1325 return delivered
1326 }
1327 }
1328
1329
1330 if t.idleConnWait == nil {
1331 t.idleConnWait = make(map[connectMethodKey]wantConnQueue)
1332 }
1333 q := t.idleConnWait[w.key]
1334 q.cleanFrontNotWaiting()
1335 q.pushBack(w)
1336 t.idleConnWait[w.key] = q
1337 return false
1338 }
1339
1340
1341 func (t *Transport) removeIdleConn(pconn *persistConn) bool {
1342 if pconn.isClientConn {
1343 return true
1344 }
1345 t.idleMu.Lock()
1346 defer t.idleMu.Unlock()
1347 return t.removeIdleConnLocked(pconn)
1348 }
1349
1350
1351 func (t *Transport) removeIdleConnLocked(pconn *persistConn) bool {
1352 if pconn.idleTimer != nil {
1353 pconn.idleTimer.Stop()
1354 }
1355 t.idleLRU.remove(pconn)
1356 key := pconn.cacheKey
1357 pconns := t.idleConn[key]
1358 var removed bool
1359 switch len(pconns) {
1360 case 0:
1361
1362 case 1:
1363 if pconns[0] == pconn {
1364 delete(t.idleConn, key)
1365 removed = true
1366 }
1367 default:
1368 for i, v := range pconns {
1369 if v != pconn {
1370 continue
1371 }
1372
1373
1374 copy(pconns[i:], pconns[i+1:])
1375 t.idleConn[key] = pconns[:len(pconns)-1]
1376 removed = true
1377 break
1378 }
1379 }
1380 return removed
1381 }
1382
1383 var zeroDialer net.Dialer
1384
1385 func (t *Transport) dial(ctx context.Context, network, addr string) (net.Conn, error) {
1386 if t.DialContext != nil {
1387 c, err := t.DialContext(ctx, network, addr)
1388 if c == nil && err == nil {
1389 err = errors.New("net/http: Transport.DialContext hook returned (nil, nil)")
1390 }
1391 return c, err
1392 }
1393 if t.Dial != nil {
1394 c, err := t.Dial(network, addr)
1395 if c == nil && err == nil {
1396 err = errors.New("net/http: Transport.Dial hook returned (nil, nil)")
1397 }
1398 return c, err
1399 }
1400 return zeroDialer.DialContext(ctx, network, addr)
1401 }
1402
1403
1404
1405
1406
1407
1408
1409 type wantConn struct {
1410 cm connectMethod
1411 key connectMethodKey
1412
1413
1414
1415
1416 beforeDial func()
1417 afterDial func()
1418
1419 mu sync.Mutex
1420 ctx context.Context
1421 cancelCtx context.CancelFunc
1422 done bool
1423 result chan connOrError
1424 }
1425
1426 type connOrError struct {
1427 pc *persistConn
1428 err error
1429 idleAt time.Time
1430 }
1431
1432
1433 func (w *wantConn) waiting() bool {
1434 w.mu.Lock()
1435 defer w.mu.Unlock()
1436
1437 return !w.done
1438 }
1439
1440
1441 func (w *wantConn) getCtxForDial() context.Context {
1442 w.mu.Lock()
1443 defer w.mu.Unlock()
1444
1445 return w.ctx
1446 }
1447
1448
1449 func (w *wantConn) tryDeliver(pc *persistConn, err error, idleAt time.Time) bool {
1450 w.mu.Lock()
1451 defer w.mu.Unlock()
1452
1453 if w.done {
1454 return false
1455 }
1456 if (pc == nil) == (err == nil) {
1457 panic("net/http: internal error: misuse of tryDeliver")
1458 }
1459 w.ctx = nil
1460 w.done = true
1461
1462 w.result <- connOrError{pc: pc, err: err, idleAt: idleAt}
1463 close(w.result)
1464
1465 return true
1466 }
1467
1468
1469
1470 func (w *wantConn) cancel(t *Transport) {
1471 w.mu.Lock()
1472 var pc *persistConn
1473 if w.done {
1474 if r, ok := <-w.result; ok {
1475 pc = r.pc
1476 }
1477 } else {
1478 close(w.result)
1479 }
1480 w.ctx = nil
1481 w.done = true
1482 w.mu.Unlock()
1483
1484
1485
1486
1487 if pc != nil && pc.alt == nil {
1488 t.putOrCloseIdleConn(pc)
1489 }
1490 }
1491
1492
1493 type wantConnQueue struct {
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504 head []*wantConn
1505 headPos int
1506 tail []*wantConn
1507 }
1508
1509
1510 func (q *wantConnQueue) len() int {
1511 return len(q.head) - q.headPos + len(q.tail)
1512 }
1513
1514
1515 func (q *wantConnQueue) pushBack(w *wantConn) {
1516 q.tail = append(q.tail, w)
1517 }
1518
1519
1520 func (q *wantConnQueue) popFront() *wantConn {
1521 if q.headPos >= len(q.head) {
1522 if len(q.tail) == 0 {
1523 return nil
1524 }
1525
1526 q.head, q.headPos, q.tail = q.tail, 0, q.head[:0]
1527 }
1528 w := q.head[q.headPos]
1529 q.head[q.headPos] = nil
1530 q.headPos++
1531 return w
1532 }
1533
1534
1535 func (q *wantConnQueue) peekFront() *wantConn {
1536 if q.headPos < len(q.head) {
1537 return q.head[q.headPos]
1538 }
1539 if len(q.tail) > 0 {
1540 return q.tail[0]
1541 }
1542 return nil
1543 }
1544
1545
1546
1547 func (q *wantConnQueue) cleanFrontNotWaiting() (cleaned bool) {
1548 for {
1549 w := q.peekFront()
1550 if w == nil || w.waiting() {
1551 return cleaned
1552 }
1553 q.popFront()
1554 cleaned = true
1555 }
1556 }
1557
1558
1559 func (q *wantConnQueue) cleanFrontCanceled() {
1560 for {
1561 w := q.peekFront()
1562 if w == nil || w.cancelCtx != nil {
1563 return
1564 }
1565 q.popFront()
1566 }
1567 }
1568
1569
1570
1571 func (q *wantConnQueue) all(f func(*wantConn)) {
1572 for _, w := range q.head[q.headPos:] {
1573 f(w)
1574 }
1575 for _, w := range q.tail {
1576 f(w)
1577 }
1578 }
1579
1580 func (t *Transport) customDialTLS(ctx context.Context, network, addr string) (conn net.Conn, err error) {
1581 if t.DialTLSContext != nil {
1582 conn, err = t.DialTLSContext(ctx, network, addr)
1583 } else {
1584 conn, err = t.DialTLS(network, addr)
1585 }
1586 if conn == nil && err == nil {
1587 err = errors.New("net/http: Transport.DialTLS or DialTLSContext returned (nil, nil)")
1588 }
1589 return
1590 }
1591
1592
1593
1594
1595
1596 func (t *Transport) getConn(treq *transportRequest, cm connectMethod) (_ *persistConn, err error) {
1597 req := treq.Request
1598 trace := treq.trace
1599 ctx := req.Context()
1600 if trace != nil && trace.GetConn != nil {
1601 trace.GetConn(cm.addr())
1602 }
1603
1604
1605
1606
1607
1608
1609 dialCtx, dialCancel := context.WithCancel(context.WithoutCancel(ctx))
1610
1611 w := &wantConn{
1612 cm: cm,
1613 key: cm.key(),
1614 ctx: dialCtx,
1615 cancelCtx: dialCancel,
1616 result: make(chan connOrError, 1),
1617 beforeDial: testHookPrePendingDial,
1618 afterDial: testHookPostPendingDial,
1619 }
1620 defer func() {
1621 if err != nil {
1622 w.cancel(t)
1623 }
1624 }()
1625
1626
1627 if delivered := t.queueForIdleConn(w); !delivered {
1628 t.queueForDial(w)
1629 }
1630
1631
1632 select {
1633 case r := <-w.result:
1634
1635
1636 if r.pc != nil && r.pc.alt == nil && trace != nil && trace.GotConn != nil {
1637 info := httptrace.GotConnInfo{
1638 Conn: r.pc.conn,
1639 Reused: r.pc.isReused(),
1640 }
1641 if !r.idleAt.IsZero() {
1642 info.WasIdle = true
1643 info.IdleTime = time.Since(r.idleAt)
1644 }
1645 trace.GotConn(info)
1646 }
1647 if r.err != nil {
1648
1649
1650
1651 select {
1652 case <-treq.ctx.Done():
1653 err := context.Cause(treq.ctx)
1654 if err == errRequestCanceled {
1655 err = errRequestCanceledConn
1656 }
1657 return nil, err
1658 default:
1659
1660 }
1661 }
1662 return r.pc, r.err
1663 case <-treq.ctx.Done():
1664 err := context.Cause(treq.ctx)
1665 if err == errRequestCanceled {
1666 err = errRequestCanceledConn
1667 }
1668 return nil, err
1669 }
1670 }
1671
1672
1673
1674 func (t *Transport) queueForDial(w *wantConn) {
1675 w.beforeDial()
1676
1677 t.connsPerHostMu.Lock()
1678 defer t.connsPerHostMu.Unlock()
1679
1680 if t.MaxConnsPerHost <= 0 {
1681 t.startDialConnForLocked(w)
1682 return
1683 }
1684
1685 if n := t.connsPerHost[w.key]; n < t.MaxConnsPerHost {
1686 if t.connsPerHost == nil {
1687 t.connsPerHost = make(map[connectMethodKey]int)
1688 }
1689 t.connsPerHost[w.key] = n + 1
1690 t.startDialConnForLocked(w)
1691 return
1692 }
1693
1694 if t.connsPerHostWait == nil {
1695 t.connsPerHostWait = make(map[connectMethodKey]wantConnQueue)
1696 }
1697 q := t.connsPerHostWait[w.key]
1698 q.cleanFrontNotWaiting()
1699 q.pushBack(w)
1700 t.connsPerHostWait[w.key] = q
1701 }
1702
1703
1704
1705 func (t *Transport) startDialConnForLocked(w *wantConn) {
1706 t.dialsInProgress.cleanFrontCanceled()
1707 t.dialsInProgress.pushBack(w)
1708 go func() {
1709 t.dialConnFor(w)
1710 t.connsPerHostMu.Lock()
1711 defer t.connsPerHostMu.Unlock()
1712 w.cancelCtx = nil
1713 }()
1714 }
1715
1716
1717
1718
1719 func (t *Transport) dialConnFor(w *wantConn) {
1720 defer w.afterDial()
1721 ctx := w.getCtxForDial()
1722 if ctx == nil {
1723 t.decConnsPerHost(w.key)
1724 return
1725 }
1726
1727 const isClientConn = false
1728 pc, err := t.dialConn(ctx, w.cm, isClientConn, nil)
1729 delivered := w.tryDeliver(pc, err, time.Time{})
1730 if err == nil && (!delivered || pc.alt != nil) {
1731
1732
1733
1734 t.putOrCloseIdleConn(pc)
1735 }
1736 if err != nil {
1737 t.decConnsPerHost(w.key)
1738 }
1739 }
1740
1741
1742
1743 func (t *Transport) decConnsPerHost(key connectMethodKey) {
1744 if t.MaxConnsPerHost <= 0 {
1745 return
1746 }
1747
1748 t.connsPerHostMu.Lock()
1749 defer t.connsPerHostMu.Unlock()
1750 n := t.connsPerHost[key]
1751 if n == 0 {
1752
1753
1754 panic("net/http: internal error: connCount underflow")
1755 }
1756
1757
1758
1759
1760
1761 if q := t.connsPerHostWait[key]; q.len() > 0 {
1762 done := false
1763 for q.len() > 0 {
1764 w := q.popFront()
1765 if w.waiting() {
1766 t.startDialConnForLocked(w)
1767 done = true
1768 break
1769 }
1770 }
1771 if q.len() == 0 {
1772 delete(t.connsPerHostWait, key)
1773 } else {
1774
1775
1776 t.connsPerHostWait[key] = q
1777 }
1778 if done {
1779 return
1780 }
1781 }
1782
1783
1784 if n--; n == 0 {
1785 delete(t.connsPerHost, key)
1786 } else {
1787 t.connsPerHost[key] = n
1788 }
1789 }
1790
1791 func (t *Transport) tlsConfigForDial(host string) (*tls.Config, error) {
1792 firstTLSHost, _, err := net.SplitHostPort(host)
1793 if err != nil {
1794 return nil, err
1795 }
1796 cfg := cloneTLSConfig(t.TLSClientConfig)
1797 if cfg.ServerName == "" {
1798 cfg.ServerName = firstTLSHost
1799 }
1800 return cfg, nil
1801 }
1802
1803
1804
1805
1806 func (pconn *persistConn) addTLS(ctx context.Context, addr string, trace *httptrace.ClientTrace) error {
1807 cfg, err := pconn.t.tlsConfigForDial(addr)
1808 if err != nil {
1809 pconn.conn.Close()
1810 return err
1811 }
1812 if pconn.cacheKey.onlyH1 {
1813 cfg.NextProtos = nil
1814 }
1815 plainConn := pconn.conn
1816 tlsConn := tls.Client(plainConn, cfg)
1817 errc := make(chan error, 2)
1818 var timer *time.Timer
1819 if d := pconn.t.TLSHandshakeTimeout; d != 0 {
1820 timer = time.AfterFunc(d, func() {
1821 errc <- tlsHandshakeTimeoutError{}
1822 })
1823 }
1824 go func() {
1825 if trace != nil && trace.TLSHandshakeStart != nil {
1826 trace.TLSHandshakeStart()
1827 }
1828 err := tlsConn.HandshakeContext(ctx)
1829 if timer != nil {
1830 timer.Stop()
1831 }
1832 errc <- err
1833 }()
1834 if err := <-errc; err != nil {
1835 plainConn.Close()
1836 if err == (tlsHandshakeTimeoutError{}) {
1837
1838
1839 <-errc
1840 }
1841 if trace != nil && trace.TLSHandshakeDone != nil {
1842 trace.TLSHandshakeDone(tls.ConnectionState{}, err)
1843 }
1844 return err
1845 }
1846 cs := tlsConn.ConnectionState()
1847 if trace != nil && trace.TLSHandshakeDone != nil {
1848 trace.TLSHandshakeDone(cs, nil)
1849 }
1850 pconn.tlsState = &cs
1851 pconn.conn = tlsConn
1852 return nil
1853 }
1854
1855 type erringRoundTripper interface {
1856 RoundTripErr() error
1857 }
1858
1859 var testHookProxyConnectTimeout = context.WithTimeout
1860
1861 func (t *Transport) dialConn(ctx context.Context, cm connectMethod, isClientConn bool, internalStateHook func()) (pconn *persistConn, err error) {
1862
1863
1864
1865
1866 if p := t.protocols(); p.http3() {
1867 if p.HTTP1() || p.HTTP2() || p.UnencryptedHTTP2() {
1868 return nil, errors.New("http: when using HTTP3, Transport.Protocols must contain only HTTP3")
1869 }
1870 if t.h3Transport == nil {
1871 return nil, errors.New("http: Transport.Protocols contains HTTP3, but Transport does not support HTTP/3")
1872 }
1873 tlsConfig, err := t.tlsConfigForDial(cm.addr())
1874 if err != nil {
1875 return nil, err
1876 }
1877 tlsConfig.NextProtos = []string{"h3"}
1878 rt, err := t.h3Transport.DialClientConn(ctx, cm.addr(), cm.proxyURL, tlsConfig, internalStateHook)
1879 if err != nil {
1880 return nil, err
1881 }
1882 return &persistConn{
1883 t: t,
1884 cacheKey: cm.key(),
1885 alt: rt,
1886 }, nil
1887 }
1888
1889 pconn = &persistConn{
1890 t: t,
1891 cacheKey: cm.key(),
1892 reqch: make(chan requestAndChan, 1),
1893 writech: make(chan writeRequest, 1),
1894 closech: make(chan struct{}),
1895 writeErrCh: make(chan error, 1),
1896 writeLoopDone: make(chan struct{}),
1897 isClientConn: isClientConn,
1898 internalStateHook: internalStateHook,
1899 }
1900 trace := httptrace.ContextClientTrace(ctx)
1901 wrapErr := func(err error) error {
1902 if cm.proxyURL != nil {
1903
1904 return &net.OpError{Op: "proxyconnect", Net: "tcp", Err: err}
1905 }
1906 return err
1907 }
1908
1909 if rt, err := t.http2ExternalDial(ctx, cm); err != errors.ErrUnsupported {
1910 if err != nil {
1911 return nil, err
1912 }
1913 return &persistConn{t: t, cacheKey: pconn.cacheKey, alt: rt}, nil
1914 }
1915
1916 if cm.scheme() == "https" && t.hasCustomTLSDialer() {
1917 var err error
1918 pconn.conn, err = t.customDialTLS(ctx, "tcp", cm.addr())
1919 if err != nil {
1920 return nil, wrapErr(err)
1921 }
1922 type connectionStater interface {
1923 ConnectionState() tls.ConnectionState
1924 }
1925 type handshaker interface {
1926 HandshakeContext(context.Context) error
1927 }
1928 if cstater, ok := pconn.conn.(connectionStater); ok {
1929 if trace != nil && trace.TLSHandshakeStart != nil {
1930 trace.TLSHandshakeStart()
1931 }
1932 if handshaker, ok := cstater.(handshaker); ok {
1933
1934
1935 if err := handshaker.HandshakeContext(ctx); err != nil {
1936 go pconn.conn.Close()
1937 if trace != nil && trace.TLSHandshakeDone != nil {
1938 trace.TLSHandshakeDone(tls.ConnectionState{}, err)
1939 }
1940 return nil, err
1941 }
1942 }
1943 cs := cstater.ConnectionState()
1944 if trace != nil && trace.TLSHandshakeDone != nil {
1945 trace.TLSHandshakeDone(cs, nil)
1946 }
1947 pconn.tlsState = &cs
1948 }
1949 } else {
1950 conn, err := t.dial(ctx, "tcp", cm.addr())
1951 if err != nil {
1952 return nil, wrapErr(err)
1953 }
1954 pconn.conn = conn
1955 if cm.scheme() == "https" {
1956 if err = pconn.addTLS(ctx, cm.addr(), trace); err != nil {
1957 return nil, wrapErr(err)
1958 }
1959 }
1960 }
1961
1962
1963 switch {
1964 case cm.proxyURL == nil:
1965
1966 case cm.proxyURL.Scheme == "socks5" || cm.proxyURL.Scheme == "socks5h":
1967 conn := pconn.conn
1968 d := socksNewDialer("tcp", conn.RemoteAddr().String())
1969 if u := cm.proxyURL.User; u != nil {
1970 auth := &socksUsernamePassword{
1971 Username: u.Username(),
1972 }
1973 auth.Password, _ = u.Password()
1974 d.AuthMethods = []socksAuthMethod{
1975 socksAuthMethodNotRequired,
1976 socksAuthMethodUsernamePassword,
1977 }
1978 d.Authenticate = auth.Authenticate
1979 }
1980 if _, err := d.DialWithConn(ctx, conn, "tcp", cm.targetAddr); err != nil {
1981 conn.Close()
1982 return nil, err
1983 }
1984 case cm.targetScheme == "http":
1985 pconn.isProxy = true
1986 if pa := cm.proxyAuth(); pa != "" {
1987 pconn.mutateHeaderFunc = func(h Header) {
1988 h.Set("Proxy-Authorization", pa)
1989 }
1990 }
1991 case cm.targetScheme == "https":
1992 conn := pconn.conn
1993 var hdr Header
1994 if t.GetProxyConnectHeader != nil {
1995 var err error
1996 hdr, err = t.GetProxyConnectHeader(ctx, cm.proxyURL, cm.targetAddr)
1997 if err != nil {
1998 conn.Close()
1999 return nil, err
2000 }
2001 } else {
2002 hdr = t.ProxyConnectHeader
2003 }
2004 if hdr == nil {
2005 hdr = make(Header)
2006 }
2007 if pa := cm.proxyAuth(); pa != "" {
2008 hdr = hdr.Clone()
2009 hdr.Set("Proxy-Authorization", pa)
2010 }
2011 connectReq := &Request{
2012 Method: "CONNECT",
2013 URL: &url.URL{Opaque: cm.targetAddr},
2014 Host: cm.targetAddr,
2015 Header: hdr,
2016 }
2017
2018
2019
2020
2021 connectCtx, cancel := testHookProxyConnectTimeout(ctx, 1*time.Minute)
2022 defer cancel()
2023
2024 didReadResponse := make(chan struct{})
2025 var (
2026 resp *Response
2027 err error
2028 )
2029
2030 go func() {
2031 defer close(didReadResponse)
2032 err = connectReq.Write(conn)
2033 if err != nil {
2034 return
2035 }
2036
2037
2038 br := bufio.NewReader(&io.LimitedReader{R: conn, N: t.maxHeaderResponseSize()})
2039 resp, err = ReadResponse(br, connectReq)
2040 }()
2041 select {
2042 case <-connectCtx.Done():
2043 conn.Close()
2044 <-didReadResponse
2045 return nil, connectCtx.Err()
2046 case <-didReadResponse:
2047
2048 }
2049 if err != nil {
2050 conn.Close()
2051 return nil, err
2052 }
2053
2054 if t.OnProxyConnectResponse != nil {
2055 err = t.OnProxyConnectResponse(ctx, cm.proxyURL, connectReq, resp)
2056 if err != nil {
2057 conn.Close()
2058 return nil, err
2059 }
2060 }
2061
2062 if resp.StatusCode != 200 {
2063 _, text, ok := strings.Cut(resp.Status, " ")
2064 conn.Close()
2065 if !ok {
2066 return nil, errors.New("unknown status code")
2067 }
2068 return nil, errors.New(text)
2069 }
2070 }
2071
2072 if cm.proxyURL != nil && cm.targetScheme == "https" {
2073 if err := pconn.addTLS(ctx, cm.targetAddr, trace); err != nil {
2074 return nil, err
2075 }
2076 }
2077
2078
2079 unencryptedHTTP2 := pconn.tlsState == nil &&
2080 t.Protocols != nil &&
2081 t.Protocols.UnencryptedHTTP2() &&
2082 !t.Protocols.HTTP1()
2083
2084 http2 := unencryptedHTTP2 ||
2085 (pconn.tlsState != nil && pconn.tlsState.NegotiatedProtocol == "h2")
2086
2087 if http2 && t.h2Transport != nil {
2088 if isClientConn {
2089 cc, err := t.http2NewClientConn(pconn.conn, internalStateHook)
2090 if err == nil {
2091 return &persistConn{t: t, cacheKey: pconn.cacheKey, alt: cc, isClientConn: true}, nil
2092 }
2093 if err != errors.ErrUnsupported {
2094 return nil, err
2095 }
2096 } else {
2097 rt, err := t.http2AddConn(cm.targetScheme, cm.targetAddr, pconn.conn)
2098 if err == nil {
2099 return &persistConn{t: t, cacheKey: pconn.cacheKey, alt: rt}, nil
2100 }
2101 if err != errors.ErrUnsupported {
2102 return nil, err
2103 }
2104 }
2105 }
2106
2107 if isClientConn && (unencryptedHTTP2 || (pconn.tlsState != nil && pconn.tlsState.NegotiatedProtocol == "h2")) {
2108 altProto, _ := t.altProto.Load().(map[string]RoundTripper)
2109 h2, ok := altProto["https"].(newClientConner)
2110 if !ok {
2111 return nil, errors.New("http: HTTP/2 implementation does not support NewClientConn (update golang.org/x/net?)")
2112 }
2113 alt, err := h2.NewClientConn(pconn.conn, internalStateHook)
2114 if err != nil {
2115 pconn.conn.Close()
2116 return nil, err
2117 }
2118 return &persistConn{t: t, cacheKey: pconn.cacheKey, alt: alt, isClientConn: true}, nil
2119 }
2120
2121 if unencryptedHTTP2 {
2122 next, ok := t.TLSNextProto[nextProtoUnencryptedHTTP2]
2123 if !ok {
2124 return nil, errors.New("http: Transport does not support unencrypted HTTP/2")
2125 }
2126 alt := next(cm.targetAddr, unencryptedTLSConn(pconn.conn))
2127 if e, ok := alt.(erringRoundTripper); ok {
2128
2129 return nil, e.RoundTripErr()
2130 }
2131 return &persistConn{t: t, cacheKey: pconn.cacheKey, alt: alt}, nil
2132 }
2133
2134 if s := pconn.tlsState; s != nil && s.NegotiatedProtocolIsMutual && s.NegotiatedProtocol != "" {
2135 tlsConn, tlsConnOK := pconn.conn.(*tls.Conn)
2136 if next, ok := t.TLSNextProto[s.NegotiatedProtocol]; tlsConnOK && ok {
2137 alt := next(cm.targetAddr, tlsConn)
2138 if e, ok := alt.(erringRoundTripper); ok {
2139
2140 return nil, e.RoundTripErr()
2141 }
2142 return &persistConn{t: t, cacheKey: pconn.cacheKey, alt: alt}, nil
2143 }
2144 }
2145
2146 pconn.br = bufio.NewReaderSize(pconn, t.readBufferSize())
2147 pconn.bw = bufio.NewWriterSize(persistConnWriter{pconn}, t.writeBufferSize())
2148
2149 go pconn.readLoop()
2150 go pconn.writeLoop()
2151 return pconn, nil
2152 }
2153
2154
2155
2156
2157
2158
2159
2160 type persistConnWriter struct {
2161 pc *persistConn
2162 }
2163
2164 func (w persistConnWriter) Write(p []byte) (n int, err error) {
2165 n, err = w.pc.conn.Write(p)
2166 w.pc.nwrite += int64(n)
2167 return
2168 }
2169
2170
2171
2172
2173 func (w persistConnWriter) ReadFrom(r io.Reader) (n int64, err error) {
2174 n, err = io.Copy(w.pc.conn, r)
2175 w.pc.nwrite += n
2176 return
2177 }
2178
2179 var _ io.ReaderFrom = (*persistConnWriter)(nil)
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197 type connectMethod struct {
2198 _ incomparable
2199 proxyURL *url.URL
2200 targetScheme string
2201
2202
2203
2204 targetAddr string
2205 onlyH1 bool
2206 }
2207
2208 func (cm *connectMethod) key() connectMethodKey {
2209 proxyStr := ""
2210 targetAddr := cm.targetAddr
2211 if cm.proxyURL != nil {
2212 proxyStr = cm.proxyURL.String()
2213 if (cm.proxyURL.Scheme == "http" || cm.proxyURL.Scheme == "https") && cm.targetScheme == "http" {
2214 targetAddr = ""
2215 }
2216 }
2217 return connectMethodKey{
2218 proxy: proxyStr,
2219 scheme: cm.targetScheme,
2220 addr: targetAddr,
2221 onlyH1: cm.onlyH1,
2222 }
2223 }
2224
2225
2226 func (cm *connectMethod) scheme() string {
2227 if cm.proxyURL != nil {
2228 return cm.proxyURL.Scheme
2229 }
2230 return cm.targetScheme
2231 }
2232
2233
2234 func (cm *connectMethod) addr() string {
2235 if cm.proxyURL != nil {
2236 return canonicalAddr(cm.proxyURL)
2237 }
2238 return cm.targetAddr
2239 }
2240
2241
2242
2243
2244 type connectMethodKey struct {
2245 proxy, scheme, addr string
2246 onlyH1 bool
2247 }
2248
2249 func (k connectMethodKey) String() string {
2250
2251 var h1 string
2252 if k.onlyH1 {
2253 h1 = ",h1"
2254 }
2255 return fmt.Sprintf("%s|%s%s|%s", k.proxy, k.scheme, h1, k.addr)
2256 }
2257
2258
2259
2260 type persistConn struct {
2261
2262
2263
2264 alt RoundTripper
2265
2266 t *Transport
2267 cacheKey connectMethodKey
2268 conn net.Conn
2269 tlsState *tls.ConnectionState
2270 br *bufio.Reader
2271 bw *bufio.Writer
2272 nwrite int64
2273 reqch chan requestAndChan
2274 writech chan writeRequest
2275 closech chan struct{}
2276 availch chan struct{}
2277 isProxy bool
2278 sawEOF bool
2279 isClientConn bool
2280 readLimit int64
2281
2282
2283
2284
2285 writeErrCh chan error
2286
2287 writeLoopDone chan struct{}
2288
2289
2290 idleAt time.Time
2291 idleTimer *time.Timer
2292
2293 mu sync.Mutex
2294 numExpectedResponses int
2295 closed error
2296 canceledErr error
2297 reused bool
2298 reserved bool
2299 inFlight bool
2300 internalStateHook func()
2301
2302
2303
2304
2305 mutateHeaderFunc func(Header)
2306 }
2307
2308 func (pc *persistConn) maxHeaderResponseSize() int64 {
2309 return pc.t.maxHeaderResponseSize()
2310 }
2311
2312 func (pc *persistConn) Read(p []byte) (n int, err error) {
2313 if pc.readLimit <= 0 {
2314 return 0, fmt.Errorf("read limit of %d bytes exhausted", pc.maxHeaderResponseSize())
2315 }
2316 if int64(len(p)) > pc.readLimit {
2317 p = p[:pc.readLimit]
2318 }
2319 n, err = pc.conn.Read(p)
2320 if err == io.EOF {
2321 pc.sawEOF = true
2322 }
2323 pc.readLimit -= int64(n)
2324 return
2325 }
2326
2327
2328 func (pc *persistConn) isBroken() bool {
2329 pc.mu.Lock()
2330 b := pc.closed != nil
2331 pc.mu.Unlock()
2332 return b
2333 }
2334
2335
2336
2337 func (pc *persistConn) canceled() error {
2338 pc.mu.Lock()
2339 defer pc.mu.Unlock()
2340 return pc.canceledErr
2341 }
2342
2343
2344 func (pc *persistConn) isReused() bool {
2345 pc.mu.Lock()
2346 r := pc.reused
2347 pc.mu.Unlock()
2348 return r
2349 }
2350
2351 func (pc *persistConn) cancelRequest(err error) {
2352 pc.mu.Lock()
2353 defer pc.mu.Unlock()
2354 pc.canceledErr = err
2355 pc.closeLocked(errRequestCanceled)
2356 }
2357
2358
2359
2360
2361 func (pc *persistConn) closeConnIfStillIdle() {
2362 t := pc.t
2363 t.idleMu.Lock()
2364 defer t.idleMu.Unlock()
2365 if _, ok := t.idleLRU.m[pc]; !ok {
2366
2367 return
2368 }
2369 t.removeIdleConnLocked(pc)
2370 pc.close(errIdleConnTimeout)
2371 }
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381 func (pc *persistConn) mapRoundTripError(req *transportRequest, startBytesWritten int64, err error) error {
2382 if err == nil {
2383 return nil
2384 }
2385
2386
2387
2388
2389
2390
2391
2392
2393 <-pc.writeLoopDone
2394
2395
2396
2397
2398 if cerr := pc.canceled(); cerr != nil {
2399 return cerr
2400 }
2401
2402
2403 req.mu.Lock()
2404 reqErr := req.err
2405 req.mu.Unlock()
2406 if reqErr != nil {
2407 return reqErr
2408 }
2409
2410 if err == errServerClosedIdle {
2411
2412 return err
2413 }
2414
2415 if _, ok := err.(transportReadFromServerError); ok {
2416 if pc.nwrite == startBytesWritten {
2417 return nothingWrittenError{err}
2418 }
2419
2420 return err
2421 }
2422 if pc.isBroken() {
2423 if pc.nwrite == startBytesWritten {
2424 return nothingWrittenError{err}
2425 }
2426 return fmt.Errorf("net/http: HTTP/1.x transport connection broken: %w", err)
2427 }
2428 return err
2429 }
2430
2431
2432
2433
2434 var errCallerOwnsConn = errors.New("read loop ending; caller owns writable underlying conn")
2435
2436
2437
2438
2439 const maxPostCloseReadBytes = 256 << 10
2440
2441
2442
2443
2444 const maxPostCloseReadTime = 50 * time.Millisecond
2445
2446 func maybeDrainBody(body io.Reader) bool {
2447 drainedCh := make(chan bool, 1)
2448 go func() {
2449 if _, err := io.CopyN(io.Discard, body, maxPostCloseReadBytes+1); err == io.EOF {
2450 drainedCh <- true
2451 } else {
2452 drainedCh <- false
2453 }
2454 }()
2455 select {
2456 case drained := <-drainedCh:
2457 return drained
2458 case <-time.After(maxPostCloseReadTime):
2459 return false
2460 }
2461 }
2462
2463 func (pc *persistConn) readLoop() {
2464 closeErr := errReadLoopExiting
2465 defer func() {
2466 pc.close(closeErr)
2467 pc.t.removeIdleConn(pc)
2468 if pc.internalStateHook != nil {
2469 pc.internalStateHook()
2470 }
2471 }()
2472
2473 tryPutIdleConn := func(treq *transportRequest) bool {
2474 trace := treq.trace
2475 if err := pc.t.tryPutIdleConn(pc); err != nil {
2476 closeErr = err
2477 if trace != nil && trace.PutIdleConn != nil && err != errKeepAlivesDisabled {
2478 trace.PutIdleConn(err)
2479 }
2480 return false
2481 }
2482 if trace != nil && trace.PutIdleConn != nil {
2483 trace.PutIdleConn(nil)
2484 }
2485 return true
2486 }
2487
2488
2489
2490
2491 eofc := make(chan struct{})
2492 defer close(eofc)
2493
2494
2495 testHookMu.Lock()
2496 testHookReadLoopBeforeNextRead := testHookReadLoopBeforeNextRead
2497 testHookMu.Unlock()
2498
2499 alive := true
2500 for alive {
2501 pc.readLimit = pc.maxHeaderResponseSize()
2502 _, err := pc.br.Peek(1)
2503
2504 pc.mu.Lock()
2505 if pc.numExpectedResponses == 0 {
2506 pc.readLoopPeekFailLocked(err)
2507 pc.mu.Unlock()
2508 return
2509 }
2510 pc.mu.Unlock()
2511
2512 rc := <-pc.reqch
2513 trace := rc.treq.trace
2514
2515 var resp *Response
2516 if err == nil {
2517 resp, err = pc.readResponse(rc, trace)
2518 } else {
2519 err = transportReadFromServerError{err}
2520 closeErr = err
2521 }
2522
2523 if err != nil {
2524 if pc.readLimit <= 0 {
2525 err = fmt.Errorf("net/http: server response headers exceeded %d bytes; aborted", pc.maxHeaderResponseSize())
2526 }
2527
2528 select {
2529 case rc.ch <- responseAndError{err: err}:
2530 case <-rc.callerGone:
2531 return
2532 }
2533 return
2534 }
2535 pc.readLimit = maxInt64
2536
2537 pc.mu.Lock()
2538 pc.numExpectedResponses--
2539 pc.mu.Unlock()
2540
2541 bodyWritable := resp.bodyIsWritable()
2542 hasBody := rc.treq.Request.Method != "HEAD" && resp.ContentLength != 0
2543
2544 if resp.Close || rc.treq.Request.Close || resp.StatusCode <= 199 || bodyWritable {
2545
2546
2547
2548 alive = false
2549 }
2550
2551 if !hasBody || bodyWritable {
2552
2553
2554
2555
2556
2557 alive = alive &&
2558 !pc.sawEOF &&
2559 pc.wroteRequest() &&
2560 tryPutIdleConn(rc.treq)
2561
2562 if bodyWritable {
2563 closeErr = errCallerOwnsConn
2564 }
2565
2566 select {
2567 case rc.ch <- responseAndError{res: resp}:
2568 case <-rc.callerGone:
2569 return
2570 }
2571
2572 rc.treq.cancel(errRequestDone)
2573
2574
2575
2576
2577 testHookReadLoopBeforeNextRead()
2578 continue
2579 }
2580
2581 waitForBodyRead := make(chan bool, 2)
2582 body := &bodyEOFSignal{
2583 body: resp.Body,
2584 earlyCloseFn: func() error {
2585 waitForBodyRead <- false
2586 <-eofc
2587 return nil
2588
2589 },
2590 fn: func(err error) error {
2591 isEOF := err == io.EOF
2592 waitForBodyRead <- isEOF
2593 if isEOF {
2594 <-eofc
2595 } else if err != nil {
2596 if cerr := pc.canceled(); cerr != nil {
2597 return cerr
2598 }
2599 }
2600 return err
2601 },
2602 }
2603
2604 resp.Body = body
2605 if rc.addedGzip && ascii.EqualFold(resp.Header.Get("Content-Encoding"), "gzip") {
2606 resp.Body = &gzipReader{body: body}
2607 resp.Header.Del("Content-Encoding")
2608 resp.Header.Del("Content-Length")
2609 resp.ContentLength = -1
2610 resp.Uncompressed = true
2611 }
2612
2613 select {
2614 case rc.ch <- responseAndError{res: resp}:
2615 case <-rc.callerGone:
2616 return
2617 }
2618
2619
2620
2621
2622 select {
2623 case bodyEOF := <-waitForBodyRead:
2624 tryDrain := !bodyEOF && resp.ContentLength <= maxPostCloseReadBytes
2625 if tryDrain {
2626 eofc <- struct{}{}
2627 bodyEOF = maybeDrainBody(body.body)
2628 }
2629 alive = alive &&
2630 bodyEOF &&
2631 !pc.sawEOF &&
2632 pc.wroteRequest() &&
2633 tryPutIdleConn(rc.treq)
2634 if !tryDrain && bodyEOF {
2635 eofc <- struct{}{}
2636 }
2637 case <-rc.treq.ctx.Done():
2638 alive = false
2639 pc.cancelRequest(context.Cause(rc.treq.ctx))
2640 case <-pc.closech:
2641 alive = false
2642 }
2643
2644 rc.treq.cancel(errRequestDone)
2645 testHookReadLoopBeforeNextRead()
2646 }
2647 }
2648
2649 func (pc *persistConn) readLoopPeekFailLocked(peekErr error) {
2650 if pc.closed != nil {
2651 return
2652 }
2653 if n := pc.br.Buffered(); n > 0 {
2654 buf, _ := pc.br.Peek(n)
2655 if is408Message(buf) {
2656 pc.closeLocked(errServerClosedIdle)
2657 return
2658 } else {
2659 log.Printf("Unsolicited response received on idle HTTP channel starting with %q; err=%v", buf, peekErr)
2660 }
2661 }
2662 if peekErr == io.EOF {
2663
2664 pc.closeLocked(errServerClosedIdle)
2665 } else {
2666 pc.closeLocked(fmt.Errorf("readLoopPeekFailLocked: %w", peekErr))
2667 }
2668 }
2669
2670
2671
2672
2673 func is408Message(buf []byte) bool {
2674 if len(buf) < len("HTTP/1.x 408") {
2675 return false
2676 }
2677 if string(buf[:7]) != "HTTP/1." {
2678 return false
2679 }
2680 return string(buf[8:12]) == " 408"
2681 }
2682
2683
2684
2685
2686 func (pc *persistConn) readResponse(rc requestAndChan, trace *httptrace.ClientTrace) (resp *Response, err error) {
2687 if trace != nil && trace.GotFirstResponseByte != nil {
2688 if peek, err := pc.br.Peek(1); err == nil && len(peek) == 1 {
2689 trace.GotFirstResponseByte()
2690 }
2691 }
2692
2693 continueCh := rc.continueCh
2694 for {
2695 resp, err = ReadResponse(pc.br, rc.treq.Request)
2696 if err != nil {
2697 return
2698 }
2699 resCode := resp.StatusCode
2700 if continueCh != nil && resCode == StatusContinue {
2701 if trace != nil && trace.Got100Continue != nil {
2702 trace.Got100Continue()
2703 }
2704 continueCh <- struct{}{}
2705 continueCh = nil
2706 }
2707 is1xx := 100 <= resCode && resCode <= 199
2708
2709 is1xxNonTerminal := is1xx && resCode != StatusSwitchingProtocols
2710 if is1xxNonTerminal {
2711 if trace != nil && trace.Got1xxResponse != nil {
2712 if err := trace.Got1xxResponse(resCode, textproto.MIMEHeader(resp.Header)); err != nil {
2713 return nil, err
2714 }
2715
2716
2717
2718
2719
2720
2721
2722 pc.readLimit = pc.maxHeaderResponseSize()
2723 }
2724 continue
2725 }
2726 break
2727 }
2728 if resp.isProtocolSwitch() {
2729 resp.Body = newReadWriteCloserBody(pc.br, pc.conn)
2730 }
2731 if continueCh != nil {
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744 if resp.Close || rc.treq.Request.Close {
2745 close(continueCh)
2746 } else {
2747 continueCh <- struct{}{}
2748 }
2749 }
2750
2751 resp.TLS = pc.tlsState
2752 return
2753 }
2754
2755
2756
2757
2758 func (pc *persistConn) waitForContinue(continueCh <-chan struct{}) func() bool {
2759 if continueCh == nil {
2760 return nil
2761 }
2762 return func() bool {
2763 timer := time.NewTimer(pc.t.ExpectContinueTimeout)
2764 defer timer.Stop()
2765
2766 select {
2767 case _, ok := <-continueCh:
2768 return ok
2769 case <-timer.C:
2770 return true
2771 case <-pc.closech:
2772 return false
2773 }
2774 }
2775 }
2776
2777 func newReadWriteCloserBody(br *bufio.Reader, rwc io.ReadWriteCloser) io.ReadWriteCloser {
2778 body := &readWriteCloserBody{ReadWriteCloser: rwc}
2779 if br.Buffered() != 0 {
2780 body.br = br
2781 }
2782 return body
2783 }
2784
2785
2786
2787
2788
2789
2790 type readWriteCloserBody struct {
2791 _ incomparable
2792 br *bufio.Reader
2793 io.ReadWriteCloser
2794 }
2795
2796 func (b *readWriteCloserBody) Read(p []byte) (n int, err error) {
2797 if b.br != nil {
2798 if n := b.br.Buffered(); len(p) > n {
2799 p = p[:n]
2800 }
2801 n, err = b.br.Read(p)
2802 if b.br.Buffered() == 0 {
2803 b.br = nil
2804 }
2805 return n, err
2806 }
2807 return b.ReadWriteCloser.Read(p)
2808 }
2809
2810 func (b *readWriteCloserBody) CloseWrite() error {
2811 if cw, ok := b.ReadWriteCloser.(interface{ CloseWrite() error }); ok {
2812 return cw.CloseWrite()
2813 }
2814 return fmt.Errorf("CloseWrite: %w", ErrNotSupported)
2815 }
2816
2817
2818 type nothingWrittenError struct {
2819 error
2820 }
2821
2822 func (nwe nothingWrittenError) Unwrap() error {
2823 return nwe.error
2824 }
2825
2826 func (pc *persistConn) writeLoop() {
2827 defer close(pc.writeLoopDone)
2828 for {
2829 select {
2830 case wr := <-pc.writech:
2831 startBytesWritten := pc.nwrite
2832 err := wr.req.Request.write(pc.bw, pc.isProxy, wr.req.extra, pc.waitForContinue(wr.continueCh))
2833 if bre, ok := err.(requestBodyReadError); ok {
2834 err = bre.error
2835
2836
2837
2838
2839
2840
2841
2842 wr.req.setError(err)
2843 }
2844 if err == nil {
2845 err = pc.bw.Flush()
2846 }
2847 if err != nil {
2848 if pc.nwrite == startBytesWritten {
2849 err = nothingWrittenError{err}
2850 }
2851 }
2852 pc.writeErrCh <- err
2853 wr.ch <- err
2854 if err != nil {
2855 pc.close(err)
2856 return
2857 }
2858 case <-pc.closech:
2859 return
2860 }
2861 }
2862 }
2863
2864
2865
2866
2867
2868
2869
2870 var maxWriteWaitBeforeConnReuse = 50 * time.Millisecond
2871
2872
2873
2874 func (pc *persistConn) wroteRequest() bool {
2875 select {
2876 case err := <-pc.writeErrCh:
2877
2878
2879 return err == nil
2880 default:
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891 t := time.NewTimer(maxWriteWaitBeforeConnReuse)
2892 defer t.Stop()
2893 select {
2894 case err := <-pc.writeErrCh:
2895 return err == nil
2896 case <-t.C:
2897 return false
2898 }
2899 }
2900 }
2901
2902
2903
2904 type responseAndError struct {
2905 _ incomparable
2906 res *Response
2907 err error
2908 }
2909
2910 type requestAndChan struct {
2911 _ incomparable
2912 treq *transportRequest
2913 ch chan responseAndError
2914
2915
2916
2917
2918 addedGzip bool
2919
2920
2921
2922
2923
2924 continueCh chan<- struct{}
2925
2926 callerGone <-chan struct{}
2927 }
2928
2929
2930
2931
2932
2933 type writeRequest struct {
2934 req *transportRequest
2935 ch chan<- error
2936
2937
2938
2939
2940 continueCh <-chan struct{}
2941 }
2942
2943
2944
2945 type timeoutError struct {
2946 err string
2947 }
2948
2949 func (e *timeoutError) Error() string { return e.err }
2950 func (e *timeoutError) Timeout() bool { return true }
2951 func (e *timeoutError) Temporary() bool { return true }
2952 func (e *timeoutError) Is(err error) bool { return err == context.DeadlineExceeded }
2953
2954 var errTimeout error = &timeoutError{"net/http: timeout awaiting response headers"}
2955
2956
2957
2958 var errRequestCanceled = internal.ErrRequestCanceled
2959 var errRequestCanceledConn = errors.New("net/http: request canceled while waiting for connection")
2960
2961
2962
2963 var errRequestDone = errors.New("net/http: request completed")
2964
2965 func nop() {}
2966
2967
2968 var (
2969 testHookEnterRoundTrip = nop
2970 testHookWaitResLoop = nop
2971 testHookRoundTripRetried = nop
2972 testHookPrePendingDial = nop
2973 testHookPostPendingDial = nop
2974
2975 testHookMu sync.Locker = fakeLocker{}
2976 testHookReadLoopBeforeNextRead = nop
2977 )
2978
2979 func (pc *persistConn) waitForAvailability(ctx context.Context) error {
2980 select {
2981 case <-pc.availch:
2982 return nil
2983 case <-pc.closech:
2984 return pc.closed
2985 case <-ctx.Done():
2986 return ctx.Err()
2987 }
2988 }
2989
2990 func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err error) {
2991 testHookEnterRoundTrip()
2992
2993 pc.mu.Lock()
2994 if pc.isClientConn {
2995 if !pc.reserved {
2996 pc.mu.Unlock()
2997 if err := pc.waitForAvailability(req.ctx); err != nil {
2998 return nil, err
2999 }
3000 pc.mu.Lock()
3001 }
3002 pc.reserved = false
3003 pc.inFlight = true
3004 }
3005 pc.numExpectedResponses++
3006 headerFn := pc.mutateHeaderFunc
3007 pc.mu.Unlock()
3008
3009 if headerFn != nil {
3010 headerFn(req.extraHeaders())
3011 }
3012
3013
3014
3015
3016
3017 requestedGzip := false
3018 if !pc.t.DisableCompression &&
3019 req.Header.Get("Accept-Encoding") == "" &&
3020 req.Header.Get("Range") == "" &&
3021 req.Method != "HEAD" {
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034 requestedGzip = true
3035 req.extraHeaders().Set("Accept-Encoding", "gzip")
3036 }
3037
3038 var continueCh chan struct{}
3039 if req.ProtoAtLeast(1, 1) && req.Body != nil && req.expectsContinue() {
3040 continueCh = make(chan struct{}, 1)
3041 }
3042
3043 if pc.t.DisableKeepAlives &&
3044 !req.wantsClose() &&
3045 !isProtocolSwitchHeader(req.Header) {
3046 req.extraHeaders().Set("Connection", "close")
3047 }
3048
3049 gone := make(chan struct{})
3050 defer close(gone)
3051
3052 const debugRoundTrip = false
3053
3054
3055
3056
3057 startBytesWritten := pc.nwrite
3058 writeErrCh := make(chan error, 1)
3059 pc.writech <- writeRequest{req, writeErrCh, continueCh}
3060
3061 resc := make(chan responseAndError)
3062 pc.reqch <- requestAndChan{
3063 treq: req,
3064 ch: resc,
3065 addedGzip: requestedGzip,
3066 continueCh: continueCh,
3067 callerGone: gone,
3068 }
3069
3070 handleResponse := func(re responseAndError) (*Response, error) {
3071 if (re.res == nil) == (re.err == nil) {
3072 panic(fmt.Sprintf("internal error: exactly one of res or err should be set; nil=%v", re.res == nil))
3073 }
3074 if debugRoundTrip {
3075 req.logf("resc recv: %p, %T/%#v", re.res, re.err, re.err)
3076 }
3077 if re.err != nil {
3078 return nil, pc.mapRoundTripError(req, startBytesWritten, re.err)
3079 }
3080 return re.res, nil
3081 }
3082
3083 var respHeaderTimer <-chan time.Time
3084 ctxDoneChan := req.ctx.Done()
3085 pcClosed := pc.closech
3086 for {
3087 testHookWaitResLoop()
3088 select {
3089 case err := <-writeErrCh:
3090 if debugRoundTrip {
3091 req.logf("writeErrCh recv: %T/%#v", err, err)
3092 }
3093 if err != nil {
3094 pc.close(fmt.Errorf("write error: %w", err))
3095 return nil, pc.mapRoundTripError(req, startBytesWritten, err)
3096 }
3097 if d := pc.t.ResponseHeaderTimeout; d > 0 {
3098 if debugRoundTrip {
3099 req.logf("starting timer for %v", d)
3100 }
3101 timer := time.NewTimer(d)
3102 defer timer.Stop()
3103 respHeaderTimer = timer.C
3104 }
3105 case <-pcClosed:
3106 select {
3107 case re := <-resc:
3108
3109
3110
3111 return handleResponse(re)
3112 default:
3113 }
3114 if debugRoundTrip {
3115 req.logf("closech recv: %T %#v", pc.closed, pc.closed)
3116 }
3117 return nil, pc.mapRoundTripError(req, startBytesWritten, pc.closed)
3118 case <-respHeaderTimer:
3119 if debugRoundTrip {
3120 req.logf("timeout waiting for response headers.")
3121 }
3122 pc.close(errTimeout)
3123 return nil, errTimeout
3124 case re := <-resc:
3125 return handleResponse(re)
3126 case <-ctxDoneChan:
3127 select {
3128 case re := <-resc:
3129
3130
3131
3132 return handleResponse(re)
3133 default:
3134 }
3135 pc.cancelRequest(context.Cause(req.ctx))
3136 }
3137 }
3138 }
3139
3140
3141
3142 type tLogKey struct{}
3143
3144 func (tr *transportRequest) logf(format string, args ...any) {
3145 if logf, ok := tr.Request.Context().Value(tLogKey{}).(func(string, ...any)); ok {
3146 logf(time.Now().Format(time.RFC3339Nano)+": "+format, args...)
3147 }
3148 }
3149
3150
3151
3152 func (pc *persistConn) markReused() {
3153 pc.mu.Lock()
3154 pc.reused = true
3155 pc.mu.Unlock()
3156 }
3157
3158
3159
3160
3161
3162
3163 func (pc *persistConn) close(err error) {
3164 pc.mu.Lock()
3165 defer pc.mu.Unlock()
3166 pc.closeLocked(err)
3167 }
3168
3169 func (pc *persistConn) closeLocked(err error) {
3170 if err == nil {
3171 panic("nil error")
3172 }
3173 if pc.closed == nil {
3174 pc.closed = err
3175 pc.t.decConnsPerHost(pc.cacheKey)
3176
3177
3178
3179 if pc.alt == nil {
3180 if err != errCallerOwnsConn {
3181 pc.conn.Close()
3182 }
3183 close(pc.closech)
3184 } else {
3185 if cc, ok := pc.alt.(io.Closer); ok {
3186 cc.Close()
3187 }
3188 }
3189 }
3190 pc.mutateHeaderFunc = nil
3191 }
3192
3193 func schemePort(scheme string) string {
3194 switch scheme {
3195 case "http":
3196 return "80"
3197 case "https":
3198 return "443"
3199 case "socks5", "socks5h":
3200 return "1080"
3201 default:
3202 return ""
3203 }
3204 }
3205
3206 func idnaASCIIFromURL(url *url.URL) string {
3207 addr := url.Hostname()
3208 if v, err := idnaASCII(addr); err == nil {
3209 addr = v
3210 }
3211 return addr
3212 }
3213
3214
3215 func canonicalAddr(url *url.URL) string {
3216 port := url.Port()
3217 if port == "" {
3218 port = schemePort(url.Scheme)
3219 }
3220 return net.JoinHostPort(idnaASCIIFromURL(url), port)
3221 }
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234 type bodyEOFSignal struct {
3235 body io.ReadCloser
3236 mu sync.Mutex
3237 closed bool
3238 rerr error
3239 fn func(error) error
3240 earlyCloseFn func() error
3241 }
3242
3243 var errReadOnClosedResBody = errors.New("http: read on closed response body")
3244 var errConcurrentReadOnResBody = errors.New("http: concurrent read on response body")
3245
3246 func (es *bodyEOFSignal) Read(p []byte) (n int, err error) {
3247 es.mu.Lock()
3248 closed, rerr := es.closed, es.rerr
3249 es.mu.Unlock()
3250 if closed {
3251 return 0, errReadOnClosedResBody
3252 }
3253 if rerr != nil {
3254 return 0, rerr
3255 }
3256
3257 n, err = es.body.Read(p)
3258 if err != nil {
3259 es.mu.Lock()
3260 defer es.mu.Unlock()
3261 if es.rerr == nil {
3262 es.rerr = err
3263 }
3264 err = es.condfn(err)
3265 }
3266 return
3267 }
3268
3269 func (es *bodyEOFSignal) Close() error {
3270 es.mu.Lock()
3271 defer es.mu.Unlock()
3272 if es.closed {
3273 return nil
3274 }
3275 es.closed = true
3276 if es.earlyCloseFn != nil && es.rerr != io.EOF {
3277 return es.earlyCloseFn()
3278 }
3279 err := es.body.Close()
3280 return es.condfn(err)
3281 }
3282
3283
3284 func (es *bodyEOFSignal) condfn(err error) error {
3285 if es.fn == nil {
3286 return err
3287 }
3288 err = es.fn(err)
3289 es.fn = nil
3290 return err
3291 }
3292
3293
3294
3295
3296
3297 type gzipReader struct {
3298 _ incomparable
3299 body *bodyEOFSignal
3300 mu sync.Mutex
3301 zr *gzip.Reader
3302 zerr error
3303 }
3304
3305 type eofReader struct{}
3306
3307 func (eofReader) Read([]byte) (int, error) { return 0, io.EOF }
3308 func (eofReader) ReadByte() (byte, error) { return 0, io.EOF }
3309
3310 var gzipPool = sync.Pool{New: func() any { return new(gzip.Reader) }}
3311
3312
3313 func gzipPoolGet(r io.Reader) (*gzip.Reader, error) {
3314 zr := gzipPool.Get().(*gzip.Reader)
3315 if err := zr.Reset(r); err != nil {
3316 gzipPoolPut(zr)
3317 return nil, err
3318 }
3319 return zr, nil
3320 }
3321
3322
3323 func gzipPoolPut(zr *gzip.Reader) {
3324
3325
3326 var r flate.Reader = eofReader{}
3327 zr.Reset(r)
3328 gzipPool.Put(zr)
3329 }
3330
3331
3332
3333 func (gz *gzipReader) acquire() (*gzip.Reader, error) {
3334 gz.mu.Lock()
3335 defer gz.mu.Unlock()
3336 if gz.zerr != nil {
3337 return nil, gz.zerr
3338 }
3339 if gz.zr == nil {
3340
3341
3342
3343
3344 gz.zerr = errConcurrentReadOnResBody
3345 gz.mu.Unlock()
3346 zr, err := gzipPoolGet(gz.body)
3347 gz.mu.Lock()
3348
3349 if gz.zerr != errConcurrentReadOnResBody {
3350 if zr != nil {
3351 gzipPoolPut(zr)
3352 }
3353 return nil, gz.zerr
3354 }
3355 gz.zr, gz.zerr = zr, err
3356 if gz.zerr != nil {
3357 return nil, gz.zerr
3358 }
3359 }
3360 ret := gz.zr
3361 gz.zr, gz.zerr = nil, errConcurrentReadOnResBody
3362 return ret, nil
3363 }
3364
3365
3366 func (gz *gzipReader) release(zr *gzip.Reader) {
3367 gz.mu.Lock()
3368 defer gz.mu.Unlock()
3369 if gz.zerr == errConcurrentReadOnResBody {
3370 gz.zr, gz.zerr = zr, nil
3371 } else {
3372 gzipPoolPut(zr)
3373 }
3374 }
3375
3376
3377
3378 func (gz *gzipReader) close() {
3379 gz.mu.Lock()
3380 defer gz.mu.Unlock()
3381 if gz.zerr == nil && gz.zr != nil {
3382 gzipPoolPut(gz.zr)
3383 gz.zr = nil
3384 }
3385 gz.zerr = errReadOnClosedResBody
3386 }
3387
3388 func (gz *gzipReader) Read(p []byte) (n int, err error) {
3389 zr, err := gz.acquire()
3390 if err != nil {
3391 return 0, err
3392 }
3393 defer gz.release(zr)
3394
3395 return zr.Read(p)
3396 }
3397
3398 func (gz *gzipReader) Close() error {
3399 gz.close()
3400
3401 return gz.body.Close()
3402 }
3403
3404 type tlsHandshakeTimeoutError struct{}
3405
3406 func (tlsHandshakeTimeoutError) Timeout() bool { return true }
3407 func (tlsHandshakeTimeoutError) Temporary() bool { return true }
3408 func (tlsHandshakeTimeoutError) Error() string { return "net/http: TLS handshake timeout" }
3409
3410
3411
3412
3413 type fakeLocker struct{}
3414
3415 func (fakeLocker) Lock() {}
3416 func (fakeLocker) Unlock() {}
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431 func cloneTLSConfig(cfg *tls.Config) *tls.Config {
3432 if cfg == nil {
3433 return &tls.Config{}
3434 }
3435 return cfg.Clone()
3436 }
3437
3438 type connLRU struct {
3439 ll *list.List
3440 m map[*persistConn]*list.Element
3441 }
3442
3443
3444 func (cl *connLRU) add(pc *persistConn) {
3445 if cl.ll == nil {
3446 cl.ll = list.New()
3447 cl.m = make(map[*persistConn]*list.Element)
3448 }
3449 ele := cl.ll.PushFront(pc)
3450 if _, ok := cl.m[pc]; ok {
3451 panic("persistConn was already in LRU")
3452 }
3453 cl.m[pc] = ele
3454 }
3455
3456 func (cl *connLRU) removeOldest() *persistConn {
3457 ele := cl.ll.Back()
3458 pc := ele.Value.(*persistConn)
3459 cl.ll.Remove(ele)
3460 delete(cl.m, pc)
3461 return pc
3462 }
3463
3464
3465 func (cl *connLRU) remove(pc *persistConn) {
3466 if ele, ok := cl.m[pc]; ok {
3467 cl.ll.Remove(ele)
3468 delete(cl.m, pc)
3469 }
3470 }
3471
3472
3473 func (cl *connLRU) len() int {
3474 return len(cl.m)
3475 }
3476
View as plain text