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