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, 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 var ok bool
929 if t.h3Transport, ok = rt.(dialClientConner); !ok {
930 panic("http: HTTP/3 RoundTripper does not implement DialClientConn")
931 }
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 func (t *Transport) prepareTransportCancel(req *Request, origCancel context.CancelCauseFunc) context.CancelCauseFunc {
993
994
995
996
997
998
999 cancel := func(err error) {
1000 origCancel(err)
1001 t.reqMu.Lock()
1002 delete(t.reqCanceler, req)
1003 t.reqMu.Unlock()
1004 }
1005 t.reqMu.Lock()
1006 if t.reqCanceler == nil {
1007 t.reqCanceler = make(map[*Request]context.CancelCauseFunc)
1008 }
1009 t.reqCanceler[req] = cancel
1010 t.reqMu.Unlock()
1011 return cancel
1012 }
1013
1014
1015
1016
1017
1018
1019
1020 func (t *Transport) CancelRequest(req *Request) {
1021 t.reqMu.Lock()
1022 cancel := t.reqCanceler[req]
1023 t.reqMu.Unlock()
1024 if cancel != nil {
1025 cancel(errRequestCanceled)
1026 }
1027 }
1028
1029
1030
1031
1032
1033 var (
1034 envProxyOnce sync.Once
1035 envProxyFuncValue func(*url.URL) (*url.URL, error)
1036 )
1037
1038
1039
1040 func envProxyFunc() func(*url.URL) (*url.URL, error) {
1041 envProxyOnce.Do(func() {
1042 envProxyFuncValue = httpproxy.FromEnvironment().ProxyFunc()
1043 })
1044 return envProxyFuncValue
1045 }
1046
1047
1048 func resetProxyConfig() {
1049 envProxyOnce = sync.Once{}
1050 envProxyFuncValue = nil
1051 }
1052
1053 func (t *Transport) connectMethodForRequest(treq *transportRequest) (cm connectMethod, err error) {
1054 cm.targetScheme = treq.URL.Scheme
1055 cm.targetAddr = canonicalAddr(treq.URL)
1056 if t.Proxy != nil {
1057 cm.proxyURL, err = t.Proxy(treq.Request)
1058 }
1059 cm.onlyH1 = treq.requiresHTTP1()
1060 return cm, err
1061 }
1062
1063
1064
1065 func (cm *connectMethod) proxyAuth() string {
1066 if cm.proxyURL == nil {
1067 return ""
1068 }
1069 if u := cm.proxyURL.User; u != nil {
1070 username := u.Username()
1071 password, _ := u.Password()
1072 return "Basic " + basicAuth(username, password)
1073 }
1074 return ""
1075 }
1076
1077
1078 var (
1079 errKeepAlivesDisabled = errors.New("http: putIdleConn: keep alives disabled")
1080 errConnBroken = errors.New("http: putIdleConn: connection is in bad state")
1081 errCloseIdle = errors.New("http: putIdleConn: CloseIdleConnections was called")
1082 errTooManyIdle = errors.New("http: putIdleConn: too many idle connections")
1083 errTooManyIdleHost = errors.New("http: putIdleConn: too many idle connections for host")
1084 errCloseIdleConns = errors.New("http: CloseIdleConnections called")
1085 errReadLoopExiting = errors.New("http: persistConn.readLoop exiting")
1086 errIdleConnTimeout = errors.New("http: idle connection timeout")
1087
1088
1089
1090
1091
1092 errServerClosedIdle = errors.New("http: server closed idle connection")
1093 )
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103 type transportReadFromServerError struct {
1104 err error
1105 }
1106
1107 func (e transportReadFromServerError) Unwrap() error { return e.err }
1108
1109 func (e transportReadFromServerError) Error() string {
1110 return fmt.Sprintf("net/http: Transport failed to read from server: %v", e.err)
1111 }
1112
1113 func (t *Transport) putOrCloseIdleConn(pconn *persistConn) {
1114 if err := t.tryPutIdleConn(pconn); err != nil {
1115 pconn.close(err)
1116 }
1117 }
1118
1119 func (t *Transport) maxIdleConnsPerHost() int {
1120 if v := t.MaxIdleConnsPerHost; v != 0 {
1121 return v
1122 }
1123 return DefaultMaxIdleConnsPerHost
1124 }
1125
1126
1127
1128
1129
1130
1131 func (t *Transport) tryPutIdleConn(pconn *persistConn) error {
1132 if t.DisableKeepAlives || t.MaxIdleConnsPerHost < 0 {
1133 return errKeepAlivesDisabled
1134 }
1135 if pconn.isBroken() {
1136 return errConnBroken
1137 }
1138 pconn.markReused()
1139 if pconn.isClientConn {
1140
1141 defer pconn.internalStateHook()
1142 pconn.mu.Lock()
1143 defer pconn.mu.Unlock()
1144 if !pconn.inFlight {
1145 panic("pconn is not in flight")
1146 }
1147 pconn.inFlight = false
1148 select {
1149 case pconn.availch <- struct{}{}:
1150 default:
1151 panic("unable to make pconn available")
1152 }
1153 return nil
1154 }
1155
1156 t.idleMu.Lock()
1157 defer t.idleMu.Unlock()
1158
1159
1160
1161
1162 if pconn.alt != nil && t.idleLRU.m[pconn] != nil {
1163 return nil
1164 }
1165
1166
1167
1168
1169
1170 key := pconn.cacheKey
1171 if q, ok := t.idleConnWait[key]; ok {
1172 done := false
1173 if pconn.alt == nil {
1174
1175
1176 for q.len() > 0 {
1177 w := q.popFront()
1178 if w.tryDeliver(pconn, nil, time.Time{}) {
1179 done = true
1180 break
1181 }
1182 }
1183 } else {
1184
1185
1186
1187
1188 for q.len() > 0 {
1189 w := q.popFront()
1190 w.tryDeliver(pconn, nil, time.Time{})
1191 }
1192 }
1193 if q.len() == 0 {
1194 delete(t.idleConnWait, key)
1195 } else {
1196 t.idleConnWait[key] = q
1197 }
1198 if done {
1199 return nil
1200 }
1201 }
1202
1203 if t.closeIdle {
1204 return errCloseIdle
1205 }
1206 if t.idleConn == nil {
1207 t.idleConn = make(map[connectMethodKey][]*persistConn)
1208 }
1209 idles := t.idleConn[key]
1210 if len(idles) >= t.maxIdleConnsPerHost() {
1211 return errTooManyIdleHost
1212 }
1213 for _, exist := range idles {
1214 if exist == pconn {
1215 log.Fatalf("dup idle pconn %p in freelist", pconn)
1216 }
1217 }
1218 t.idleConn[key] = append(idles, pconn)
1219 t.idleLRU.add(pconn)
1220 if t.MaxIdleConns != 0 && t.idleLRU.len() > t.MaxIdleConns {
1221 oldest := t.idleLRU.removeOldest()
1222 oldest.close(errTooManyIdle)
1223 t.removeIdleConnLocked(oldest)
1224 }
1225
1226
1227
1228
1229 if t.IdleConnTimeout > 0 && pconn.alt == nil {
1230 if pconn.idleTimer != nil {
1231 pconn.idleTimer.Reset(t.IdleConnTimeout)
1232 } else {
1233 pconn.idleTimer = time.AfterFunc(t.IdleConnTimeout, pconn.closeConnIfStillIdle)
1234 }
1235 }
1236 pconn.idleAt = time.Now()
1237 return nil
1238 }
1239
1240
1241
1242
1243 func (t *Transport) queueForIdleConn(w *wantConn) (delivered bool) {
1244 if t.DisableKeepAlives {
1245 return false
1246 }
1247
1248 t.idleMu.Lock()
1249 defer t.idleMu.Unlock()
1250
1251
1252
1253 t.closeIdle = false
1254
1255 if w == nil {
1256
1257 return false
1258 }
1259
1260
1261
1262
1263 var oldTime time.Time
1264 if t.IdleConnTimeout > 0 {
1265 oldTime = time.Now().Add(-t.IdleConnTimeout)
1266 }
1267
1268
1269 if list, ok := t.idleConn[w.key]; ok {
1270 stop := false
1271 delivered := false
1272 for len(list) > 0 && !stop {
1273 pconn := list[len(list)-1]
1274
1275
1276
1277
1278 tooOld := !oldTime.IsZero() && pconn.idleAt.Round(0).Before(oldTime)
1279 if tooOld {
1280
1281
1282
1283 go pconn.closeConnIfStillIdle()
1284 }
1285 if pconn.isBroken() || tooOld {
1286
1287
1288
1289
1290
1291 list = list[:len(list)-1]
1292 continue
1293 }
1294 delivered = w.tryDeliver(pconn, nil, pconn.idleAt)
1295 if delivered {
1296 if pconn.alt != nil {
1297
1298
1299 } else {
1300
1301
1302 t.idleLRU.remove(pconn)
1303 list = list[:len(list)-1]
1304 }
1305 }
1306 stop = true
1307 }
1308 if len(list) > 0 {
1309 t.idleConn[w.key] = list
1310 } else {
1311 delete(t.idleConn, w.key)
1312 }
1313 if stop {
1314 return delivered
1315 }
1316 }
1317
1318
1319 if t.idleConnWait == nil {
1320 t.idleConnWait = make(map[connectMethodKey]wantConnQueue)
1321 }
1322 q := t.idleConnWait[w.key]
1323 q.cleanFrontNotWaiting()
1324 q.pushBack(w)
1325 t.idleConnWait[w.key] = q
1326 return false
1327 }
1328
1329
1330 func (t *Transport) removeIdleConn(pconn *persistConn) bool {
1331 if pconn.isClientConn {
1332 return true
1333 }
1334 t.idleMu.Lock()
1335 defer t.idleMu.Unlock()
1336 return t.removeIdleConnLocked(pconn)
1337 }
1338
1339
1340 func (t *Transport) removeIdleConnLocked(pconn *persistConn) bool {
1341 if pconn.idleTimer != nil {
1342 pconn.idleTimer.Stop()
1343 }
1344 t.idleLRU.remove(pconn)
1345 key := pconn.cacheKey
1346 pconns := t.idleConn[key]
1347 var removed bool
1348 switch len(pconns) {
1349 case 0:
1350
1351 case 1:
1352 if pconns[0] == pconn {
1353 delete(t.idleConn, key)
1354 removed = true
1355 }
1356 default:
1357 for i, v := range pconns {
1358 if v != pconn {
1359 continue
1360 }
1361
1362
1363 copy(pconns[i:], pconns[i+1:])
1364 t.idleConn[key] = pconns[:len(pconns)-1]
1365 removed = true
1366 break
1367 }
1368 }
1369 return removed
1370 }
1371
1372 var zeroDialer net.Dialer
1373
1374 func (t *Transport) dial(ctx context.Context, network, addr string) (net.Conn, error) {
1375 if t.DialContext != nil {
1376 c, err := t.DialContext(ctx, network, addr)
1377 if c == nil && err == nil {
1378 err = errors.New("net/http: Transport.DialContext hook returned (nil, nil)")
1379 }
1380 return c, err
1381 }
1382 if t.Dial != nil {
1383 c, err := t.Dial(network, addr)
1384 if c == nil && err == nil {
1385 err = errors.New("net/http: Transport.Dial hook returned (nil, nil)")
1386 }
1387 return c, err
1388 }
1389 return zeroDialer.DialContext(ctx, network, addr)
1390 }
1391
1392
1393
1394
1395
1396
1397
1398 type wantConn struct {
1399 cm connectMethod
1400 key connectMethodKey
1401
1402
1403
1404
1405 beforeDial func()
1406 afterDial func()
1407
1408 mu sync.Mutex
1409 ctx context.Context
1410 cancelCtx context.CancelFunc
1411 done bool
1412 result chan connOrError
1413 }
1414
1415 type connOrError struct {
1416 pc *persistConn
1417 err error
1418 idleAt time.Time
1419 }
1420
1421
1422 func (w *wantConn) waiting() bool {
1423 w.mu.Lock()
1424 defer w.mu.Unlock()
1425
1426 return !w.done
1427 }
1428
1429
1430 func (w *wantConn) getCtxForDial() context.Context {
1431 w.mu.Lock()
1432 defer w.mu.Unlock()
1433
1434 return w.ctx
1435 }
1436
1437
1438 func (w *wantConn) tryDeliver(pc *persistConn, err error, idleAt time.Time) bool {
1439 w.mu.Lock()
1440 defer w.mu.Unlock()
1441
1442 if w.done {
1443 return false
1444 }
1445 if (pc == nil) == (err == nil) {
1446 panic("net/http: internal error: misuse of tryDeliver")
1447 }
1448 w.ctx = nil
1449 w.done = true
1450
1451 w.result <- connOrError{pc: pc, err: err, idleAt: idleAt}
1452 close(w.result)
1453
1454 return true
1455 }
1456
1457
1458
1459 func (w *wantConn) cancel(t *Transport) {
1460 w.mu.Lock()
1461 var pc *persistConn
1462 if w.done {
1463 if r, ok := <-w.result; ok {
1464 pc = r.pc
1465 }
1466 } else {
1467 close(w.result)
1468 }
1469 w.ctx = nil
1470 w.done = true
1471 w.mu.Unlock()
1472
1473
1474
1475
1476 if pc != nil && pc.alt == nil {
1477 t.putOrCloseIdleConn(pc)
1478 }
1479 }
1480
1481
1482 type wantConnQueue struct {
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493 head []*wantConn
1494 headPos int
1495 tail []*wantConn
1496 }
1497
1498
1499 func (q *wantConnQueue) len() int {
1500 return len(q.head) - q.headPos + len(q.tail)
1501 }
1502
1503
1504 func (q *wantConnQueue) pushBack(w *wantConn) {
1505 q.tail = append(q.tail, w)
1506 }
1507
1508
1509 func (q *wantConnQueue) popFront() *wantConn {
1510 if q.headPos >= len(q.head) {
1511 if len(q.tail) == 0 {
1512 return nil
1513 }
1514
1515 q.head, q.headPos, q.tail = q.tail, 0, q.head[:0]
1516 }
1517 w := q.head[q.headPos]
1518 q.head[q.headPos] = nil
1519 q.headPos++
1520 return w
1521 }
1522
1523
1524 func (q *wantConnQueue) peekFront() *wantConn {
1525 if q.headPos < len(q.head) {
1526 return q.head[q.headPos]
1527 }
1528 if len(q.tail) > 0 {
1529 return q.tail[0]
1530 }
1531 return nil
1532 }
1533
1534
1535
1536 func (q *wantConnQueue) cleanFrontNotWaiting() (cleaned bool) {
1537 for {
1538 w := q.peekFront()
1539 if w == nil || w.waiting() {
1540 return cleaned
1541 }
1542 q.popFront()
1543 cleaned = true
1544 }
1545 }
1546
1547
1548 func (q *wantConnQueue) cleanFrontCanceled() {
1549 for {
1550 w := q.peekFront()
1551 if w == nil || w.cancelCtx != nil {
1552 return
1553 }
1554 q.popFront()
1555 }
1556 }
1557
1558
1559
1560 func (q *wantConnQueue) all(f func(*wantConn)) {
1561 for _, w := range q.head[q.headPos:] {
1562 f(w)
1563 }
1564 for _, w := range q.tail {
1565 f(w)
1566 }
1567 }
1568
1569 func (t *Transport) customDialTLS(ctx context.Context, network, addr string) (conn net.Conn, err error) {
1570 if t.DialTLSContext != nil {
1571 conn, err = t.DialTLSContext(ctx, network, addr)
1572 } else {
1573 conn, err = t.DialTLS(network, addr)
1574 }
1575 if conn == nil && err == nil {
1576 err = errors.New("net/http: Transport.DialTLS or DialTLSContext returned (nil, nil)")
1577 }
1578 return
1579 }
1580
1581
1582
1583
1584
1585 func (t *Transport) getConn(treq *transportRequest, cm connectMethod) (_ *persistConn, err error) {
1586 req := treq.Request
1587 trace := treq.trace
1588 ctx := req.Context()
1589 if trace != nil && trace.GetConn != nil {
1590 trace.GetConn(cm.addr())
1591 }
1592
1593
1594
1595
1596
1597
1598 dialCtx, dialCancel := context.WithCancel(context.WithoutCancel(ctx))
1599
1600 w := &wantConn{
1601 cm: cm,
1602 key: cm.key(),
1603 ctx: dialCtx,
1604 cancelCtx: dialCancel,
1605 result: make(chan connOrError, 1),
1606 beforeDial: testHookPrePendingDial,
1607 afterDial: testHookPostPendingDial,
1608 }
1609 defer func() {
1610 if err != nil {
1611 w.cancel(t)
1612 }
1613 }()
1614
1615
1616 if delivered := t.queueForIdleConn(w); !delivered {
1617 t.queueForDial(w)
1618 }
1619
1620
1621 select {
1622 case r := <-w.result:
1623
1624
1625 if r.pc != nil && r.pc.alt == nil && trace != nil && trace.GotConn != nil {
1626 info := httptrace.GotConnInfo{
1627 Conn: r.pc.conn,
1628 Reused: r.pc.isReused(),
1629 }
1630 if !r.idleAt.IsZero() {
1631 info.WasIdle = true
1632 info.IdleTime = time.Since(r.idleAt)
1633 }
1634 trace.GotConn(info)
1635 }
1636 if r.err != nil {
1637
1638
1639
1640 select {
1641 case <-treq.ctx.Done():
1642 err := context.Cause(treq.ctx)
1643 if err == errRequestCanceled {
1644 err = errRequestCanceledConn
1645 }
1646 return nil, err
1647 default:
1648
1649 }
1650 }
1651 return r.pc, r.err
1652 case <-treq.ctx.Done():
1653 err := context.Cause(treq.ctx)
1654 if err == errRequestCanceled {
1655 err = errRequestCanceledConn
1656 }
1657 return nil, err
1658 }
1659 }
1660
1661
1662
1663 func (t *Transport) queueForDial(w *wantConn) {
1664 w.beforeDial()
1665
1666 t.connsPerHostMu.Lock()
1667 defer t.connsPerHostMu.Unlock()
1668
1669 if t.MaxConnsPerHost <= 0 {
1670 t.startDialConnForLocked(w)
1671 return
1672 }
1673
1674 if n := t.connsPerHost[w.key]; n < t.MaxConnsPerHost {
1675 if t.connsPerHost == nil {
1676 t.connsPerHost = make(map[connectMethodKey]int)
1677 }
1678 t.connsPerHost[w.key] = n + 1
1679 t.startDialConnForLocked(w)
1680 return
1681 }
1682
1683 if t.connsPerHostWait == nil {
1684 t.connsPerHostWait = make(map[connectMethodKey]wantConnQueue)
1685 }
1686 q := t.connsPerHostWait[w.key]
1687 q.cleanFrontNotWaiting()
1688 q.pushBack(w)
1689 t.connsPerHostWait[w.key] = q
1690 }
1691
1692
1693
1694 func (t *Transport) startDialConnForLocked(w *wantConn) {
1695 t.dialsInProgress.cleanFrontCanceled()
1696 t.dialsInProgress.pushBack(w)
1697 go func() {
1698 t.dialConnFor(w)
1699 t.connsPerHostMu.Lock()
1700 defer t.connsPerHostMu.Unlock()
1701 w.cancelCtx = nil
1702 }()
1703 }
1704
1705
1706
1707
1708 func (t *Transport) dialConnFor(w *wantConn) {
1709 defer w.afterDial()
1710 ctx := w.getCtxForDial()
1711 if ctx == nil {
1712 t.decConnsPerHost(w.key)
1713 return
1714 }
1715
1716 const isClientConn = false
1717 pc, err := t.dialConn(ctx, w.cm, isClientConn, nil)
1718 delivered := w.tryDeliver(pc, err, time.Time{})
1719 if err == nil && (!delivered || pc.alt != nil) {
1720
1721
1722
1723 t.putOrCloseIdleConn(pc)
1724 }
1725 if err != nil {
1726 t.decConnsPerHost(w.key)
1727 }
1728 }
1729
1730
1731
1732 func (t *Transport) decConnsPerHost(key connectMethodKey) {
1733 if t.MaxConnsPerHost <= 0 {
1734 return
1735 }
1736
1737 t.connsPerHostMu.Lock()
1738 defer t.connsPerHostMu.Unlock()
1739 n := t.connsPerHost[key]
1740 if n == 0 {
1741
1742
1743 panic("net/http: internal error: connCount underflow")
1744 }
1745
1746
1747
1748
1749
1750 if q := t.connsPerHostWait[key]; q.len() > 0 {
1751 done := false
1752 for q.len() > 0 {
1753 w := q.popFront()
1754 if w.waiting() {
1755 t.startDialConnForLocked(w)
1756 done = true
1757 break
1758 }
1759 }
1760 if q.len() == 0 {
1761 delete(t.connsPerHostWait, key)
1762 } else {
1763
1764
1765 t.connsPerHostWait[key] = q
1766 }
1767 if done {
1768 return
1769 }
1770 }
1771
1772
1773 if n--; n == 0 {
1774 delete(t.connsPerHost, key)
1775 } else {
1776 t.connsPerHost[key] = n
1777 }
1778 }
1779
1780
1781
1782
1783 func (pconn *persistConn) addTLS(ctx context.Context, name string, trace *httptrace.ClientTrace) error {
1784
1785 cfg := cloneTLSConfig(pconn.t.TLSClientConfig)
1786 if cfg.ServerName == "" {
1787 cfg.ServerName = name
1788 }
1789 if pconn.cacheKey.onlyH1 {
1790 cfg.NextProtos = nil
1791 }
1792 plainConn := pconn.conn
1793 tlsConn := tls.Client(plainConn, cfg)
1794 errc := make(chan error, 2)
1795 var timer *time.Timer
1796 if d := pconn.t.TLSHandshakeTimeout; d != 0 {
1797 timer = time.AfterFunc(d, func() {
1798 errc <- tlsHandshakeTimeoutError{}
1799 })
1800 }
1801 go func() {
1802 if trace != nil && trace.TLSHandshakeStart != nil {
1803 trace.TLSHandshakeStart()
1804 }
1805 err := tlsConn.HandshakeContext(ctx)
1806 if timer != nil {
1807 timer.Stop()
1808 }
1809 errc <- err
1810 }()
1811 if err := <-errc; err != nil {
1812 plainConn.Close()
1813 if err == (tlsHandshakeTimeoutError{}) {
1814
1815
1816 <-errc
1817 }
1818 if trace != nil && trace.TLSHandshakeDone != nil {
1819 trace.TLSHandshakeDone(tls.ConnectionState{}, err)
1820 }
1821 return err
1822 }
1823 cs := tlsConn.ConnectionState()
1824 if trace != nil && trace.TLSHandshakeDone != nil {
1825 trace.TLSHandshakeDone(cs, nil)
1826 }
1827 pconn.tlsState = &cs
1828 pconn.conn = tlsConn
1829 return nil
1830 }
1831
1832 type erringRoundTripper interface {
1833 RoundTripErr() error
1834 }
1835
1836 var testHookProxyConnectTimeout = context.WithTimeout
1837
1838 func (t *Transport) dialConn(ctx context.Context, cm connectMethod, isClientConn bool, internalStateHook func()) (pconn *persistConn, err error) {
1839
1840
1841
1842
1843 if p := t.protocols(); p.http3() {
1844 if p.HTTP1() || p.HTTP2() || p.UnencryptedHTTP2() {
1845 return nil, errors.New("http: when using HTTP3, Transport.Protocols must contain only HTTP3")
1846 }
1847 if t.h3Transport == nil {
1848 return nil, errors.New("http: Transport.Protocols contains HTTP3, but Transport does not support HTTP/3")
1849 }
1850 rt, err := t.h3Transport.DialClientConn(ctx, cm.addr(), cm.proxyURL, internalStateHook)
1851 if err != nil {
1852 return nil, err
1853 }
1854 return &persistConn{
1855 t: t,
1856 cacheKey: cm.key(),
1857 alt: rt,
1858 }, nil
1859 }
1860
1861 pconn = &persistConn{
1862 t: t,
1863 cacheKey: cm.key(),
1864 reqch: make(chan requestAndChan, 1),
1865 writech: make(chan writeRequest, 1),
1866 closech: make(chan struct{}),
1867 writeErrCh: make(chan error, 1),
1868 writeLoopDone: make(chan struct{}),
1869 isClientConn: isClientConn,
1870 internalStateHook: internalStateHook,
1871 }
1872 trace := httptrace.ContextClientTrace(ctx)
1873 wrapErr := func(err error) error {
1874 if cm.proxyURL != nil {
1875
1876 return &net.OpError{Op: "proxyconnect", Net: "tcp", Err: err}
1877 }
1878 return err
1879 }
1880
1881 if rt, err := t.http2ExternalDial(ctx, cm); err != errors.ErrUnsupported {
1882 if err != nil {
1883 return nil, err
1884 }
1885 return &persistConn{t: t, cacheKey: pconn.cacheKey, alt: rt}, nil
1886 }
1887
1888 if cm.scheme() == "https" && t.hasCustomTLSDialer() {
1889 var err error
1890 pconn.conn, err = t.customDialTLS(ctx, "tcp", cm.addr())
1891 if err != nil {
1892 return nil, wrapErr(err)
1893 }
1894 type connectionStater interface {
1895 ConnectionState() tls.ConnectionState
1896 }
1897 type handshaker interface {
1898 HandshakeContext(context.Context) error
1899 }
1900 if cstater, ok := pconn.conn.(connectionStater); ok {
1901 if trace != nil && trace.TLSHandshakeStart != nil {
1902 trace.TLSHandshakeStart()
1903 }
1904 if handshaker, ok := cstater.(handshaker); ok {
1905
1906
1907 if err := handshaker.HandshakeContext(ctx); err != nil {
1908 go pconn.conn.Close()
1909 if trace != nil && trace.TLSHandshakeDone != nil {
1910 trace.TLSHandshakeDone(tls.ConnectionState{}, err)
1911 }
1912 return nil, err
1913 }
1914 }
1915 cs := cstater.ConnectionState()
1916 if trace != nil && trace.TLSHandshakeDone != nil {
1917 trace.TLSHandshakeDone(cs, nil)
1918 }
1919 pconn.tlsState = &cs
1920 }
1921 } else {
1922 conn, err := t.dial(ctx, "tcp", cm.addr())
1923 if err != nil {
1924 return nil, wrapErr(err)
1925 }
1926 pconn.conn = conn
1927 if cm.scheme() == "https" {
1928 var firstTLSHost string
1929 if firstTLSHost, _, err = net.SplitHostPort(cm.addr()); err != nil {
1930 return nil, wrapErr(err)
1931 }
1932 if err = pconn.addTLS(ctx, firstTLSHost, trace); err != nil {
1933 return nil, wrapErr(err)
1934 }
1935 }
1936 }
1937
1938
1939 switch {
1940 case cm.proxyURL == nil:
1941
1942 case cm.proxyURL.Scheme == "socks5" || cm.proxyURL.Scheme == "socks5h":
1943 conn := pconn.conn
1944 d := socksNewDialer("tcp", conn.RemoteAddr().String())
1945 if u := cm.proxyURL.User; u != nil {
1946 auth := &socksUsernamePassword{
1947 Username: u.Username(),
1948 }
1949 auth.Password, _ = u.Password()
1950 d.AuthMethods = []socksAuthMethod{
1951 socksAuthMethodNotRequired,
1952 socksAuthMethodUsernamePassword,
1953 }
1954 d.Authenticate = auth.Authenticate
1955 }
1956 if _, err := d.DialWithConn(ctx, conn, "tcp", cm.targetAddr); err != nil {
1957 conn.Close()
1958 return nil, err
1959 }
1960 case cm.targetScheme == "http":
1961 pconn.isProxy = true
1962 if pa := cm.proxyAuth(); pa != "" {
1963 pconn.mutateHeaderFunc = func(h Header) {
1964 h.Set("Proxy-Authorization", pa)
1965 }
1966 }
1967 case cm.targetScheme == "https":
1968 conn := pconn.conn
1969 var hdr Header
1970 if t.GetProxyConnectHeader != nil {
1971 var err error
1972 hdr, err = t.GetProxyConnectHeader(ctx, cm.proxyURL, cm.targetAddr)
1973 if err != nil {
1974 conn.Close()
1975 return nil, err
1976 }
1977 } else {
1978 hdr = t.ProxyConnectHeader
1979 }
1980 if hdr == nil {
1981 hdr = make(Header)
1982 }
1983 if pa := cm.proxyAuth(); pa != "" {
1984 hdr = hdr.Clone()
1985 hdr.Set("Proxy-Authorization", pa)
1986 }
1987 connectReq := &Request{
1988 Method: "CONNECT",
1989 URL: &url.URL{Opaque: cm.targetAddr},
1990 Host: cm.targetAddr,
1991 Header: hdr,
1992 }
1993
1994
1995
1996
1997 connectCtx, cancel := testHookProxyConnectTimeout(ctx, 1*time.Minute)
1998 defer cancel()
1999
2000 didReadResponse := make(chan struct{})
2001 var (
2002 resp *Response
2003 err error
2004 )
2005
2006 go func() {
2007 defer close(didReadResponse)
2008 err = connectReq.Write(conn)
2009 if err != nil {
2010 return
2011 }
2012
2013
2014 br := bufio.NewReader(&io.LimitedReader{R: conn, N: t.maxHeaderResponseSize()})
2015 resp, err = ReadResponse(br, connectReq)
2016 }()
2017 select {
2018 case <-connectCtx.Done():
2019 conn.Close()
2020 <-didReadResponse
2021 return nil, connectCtx.Err()
2022 case <-didReadResponse:
2023
2024 }
2025 if err != nil {
2026 conn.Close()
2027 return nil, err
2028 }
2029
2030 if t.OnProxyConnectResponse != nil {
2031 err = t.OnProxyConnectResponse(ctx, cm.proxyURL, connectReq, resp)
2032 if err != nil {
2033 conn.Close()
2034 return nil, err
2035 }
2036 }
2037
2038 if resp.StatusCode != 200 {
2039 _, text, ok := strings.Cut(resp.Status, " ")
2040 conn.Close()
2041 if !ok {
2042 return nil, errors.New("unknown status code")
2043 }
2044 return nil, errors.New(text)
2045 }
2046 }
2047
2048 if cm.proxyURL != nil && cm.targetScheme == "https" {
2049 if err := pconn.addTLS(ctx, cm.tlsHost(), trace); err != nil {
2050 return nil, err
2051 }
2052 }
2053
2054
2055 unencryptedHTTP2 := pconn.tlsState == nil &&
2056 t.Protocols != nil &&
2057 t.Protocols.UnencryptedHTTP2() &&
2058 !t.Protocols.HTTP1()
2059
2060 http2 := unencryptedHTTP2 ||
2061 (pconn.tlsState != nil && pconn.tlsState.NegotiatedProtocol == "h2")
2062
2063 if http2 && t.h2Transport != nil {
2064 if isClientConn {
2065 cc, err := t.http2NewClientConn(pconn.conn, internalStateHook)
2066 if err == nil {
2067 return &persistConn{t: t, cacheKey: pconn.cacheKey, alt: cc, isClientConn: true}, nil
2068 }
2069 if err != errors.ErrUnsupported {
2070 return nil, err
2071 }
2072 } else {
2073 rt, err := t.http2AddConn(cm.targetScheme, cm.targetAddr, pconn.conn)
2074 if err == nil {
2075 return &persistConn{t: t, cacheKey: pconn.cacheKey, alt: rt}, nil
2076 }
2077 if err != errors.ErrUnsupported {
2078 return nil, err
2079 }
2080 }
2081 }
2082
2083 if isClientConn && (unencryptedHTTP2 || (pconn.tlsState != nil && pconn.tlsState.NegotiatedProtocol == "h2")) {
2084 altProto, _ := t.altProto.Load().(map[string]RoundTripper)
2085 h2, ok := altProto["https"].(newClientConner)
2086 if !ok {
2087 return nil, errors.New("http: HTTP/2 implementation does not support NewClientConn (update golang.org/x/net?)")
2088 }
2089 alt, err := h2.NewClientConn(pconn.conn, internalStateHook)
2090 if err != nil {
2091 pconn.conn.Close()
2092 return nil, err
2093 }
2094 return &persistConn{t: t, cacheKey: pconn.cacheKey, alt: alt, isClientConn: true}, nil
2095 }
2096
2097 if unencryptedHTTP2 {
2098 next, ok := t.TLSNextProto[nextProtoUnencryptedHTTP2]
2099 if !ok {
2100 return nil, errors.New("http: Transport does not support unencrypted HTTP/2")
2101 }
2102 alt := next(cm.targetAddr, unencryptedTLSConn(pconn.conn))
2103 if e, ok := alt.(erringRoundTripper); ok {
2104
2105 return nil, e.RoundTripErr()
2106 }
2107 return &persistConn{t: t, cacheKey: pconn.cacheKey, alt: alt}, nil
2108 }
2109
2110 if s := pconn.tlsState; s != nil && s.NegotiatedProtocolIsMutual && s.NegotiatedProtocol != "" {
2111 tlsConn, tlsConnOK := pconn.conn.(*tls.Conn)
2112 if next, ok := t.TLSNextProto[s.NegotiatedProtocol]; tlsConnOK && ok {
2113 alt := next(cm.targetAddr, tlsConn)
2114 if e, ok := alt.(erringRoundTripper); ok {
2115
2116 return nil, e.RoundTripErr()
2117 }
2118 return &persistConn{t: t, cacheKey: pconn.cacheKey, alt: alt}, nil
2119 }
2120 }
2121
2122 pconn.br = bufio.NewReaderSize(pconn, t.readBufferSize())
2123 pconn.bw = bufio.NewWriterSize(persistConnWriter{pconn}, t.writeBufferSize())
2124
2125 go pconn.readLoop()
2126 go pconn.writeLoop()
2127 return pconn, nil
2128 }
2129
2130
2131
2132
2133
2134
2135
2136 type persistConnWriter struct {
2137 pc *persistConn
2138 }
2139
2140 func (w persistConnWriter) Write(p []byte) (n int, err error) {
2141 n, err = w.pc.conn.Write(p)
2142 w.pc.nwrite += int64(n)
2143 return
2144 }
2145
2146
2147
2148
2149 func (w persistConnWriter) ReadFrom(r io.Reader) (n int64, err error) {
2150 n, err = io.Copy(w.pc.conn, r)
2151 w.pc.nwrite += n
2152 return
2153 }
2154
2155 var _ io.ReaderFrom = (*persistConnWriter)(nil)
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173 type connectMethod struct {
2174 _ incomparable
2175 proxyURL *url.URL
2176 targetScheme string
2177
2178
2179
2180 targetAddr string
2181 onlyH1 bool
2182 }
2183
2184 func (cm *connectMethod) key() connectMethodKey {
2185 proxyStr := ""
2186 targetAddr := cm.targetAddr
2187 if cm.proxyURL != nil {
2188 proxyStr = cm.proxyURL.String()
2189 if (cm.proxyURL.Scheme == "http" || cm.proxyURL.Scheme == "https") && cm.targetScheme == "http" {
2190 targetAddr = ""
2191 }
2192 }
2193 return connectMethodKey{
2194 proxy: proxyStr,
2195 scheme: cm.targetScheme,
2196 addr: targetAddr,
2197 onlyH1: cm.onlyH1,
2198 }
2199 }
2200
2201
2202 func (cm *connectMethod) scheme() string {
2203 if cm.proxyURL != nil {
2204 return cm.proxyURL.Scheme
2205 }
2206 return cm.targetScheme
2207 }
2208
2209
2210 func (cm *connectMethod) addr() string {
2211 if cm.proxyURL != nil {
2212 return canonicalAddr(cm.proxyURL)
2213 }
2214 return cm.targetAddr
2215 }
2216
2217
2218
2219 func (cm *connectMethod) tlsHost() string {
2220 h := cm.targetAddr
2221 return removePort(h)
2222 }
2223
2224
2225
2226
2227 type connectMethodKey struct {
2228 proxy, scheme, addr string
2229 onlyH1 bool
2230 }
2231
2232 func (k connectMethodKey) String() string {
2233
2234 var h1 string
2235 if k.onlyH1 {
2236 h1 = ",h1"
2237 }
2238 return fmt.Sprintf("%s|%s%s|%s", k.proxy, k.scheme, h1, k.addr)
2239 }
2240
2241
2242
2243 type persistConn struct {
2244
2245
2246
2247 alt RoundTripper
2248
2249 t *Transport
2250 cacheKey connectMethodKey
2251 conn net.Conn
2252 tlsState *tls.ConnectionState
2253 br *bufio.Reader
2254 bw *bufio.Writer
2255 nwrite int64
2256 reqch chan requestAndChan
2257 writech chan writeRequest
2258 closech chan struct{}
2259 availch chan struct{}
2260 isProxy bool
2261 sawEOF bool
2262 isClientConn bool
2263 readLimit int64
2264
2265
2266
2267
2268 writeErrCh chan error
2269
2270 writeLoopDone chan struct{}
2271
2272
2273 idleAt time.Time
2274 idleTimer *time.Timer
2275
2276 mu sync.Mutex
2277 numExpectedResponses int
2278 closed error
2279 canceledErr error
2280 reused bool
2281 reserved bool
2282 inFlight bool
2283 internalStateHook func()
2284
2285
2286
2287
2288 mutateHeaderFunc func(Header)
2289 }
2290
2291 func (pc *persistConn) maxHeaderResponseSize() int64 {
2292 return pc.t.maxHeaderResponseSize()
2293 }
2294
2295 func (pc *persistConn) Read(p []byte) (n int, err error) {
2296 if pc.readLimit <= 0 {
2297 return 0, fmt.Errorf("read limit of %d bytes exhausted", pc.maxHeaderResponseSize())
2298 }
2299 if int64(len(p)) > pc.readLimit {
2300 p = p[:pc.readLimit]
2301 }
2302 n, err = pc.conn.Read(p)
2303 if err == io.EOF {
2304 pc.sawEOF = true
2305 }
2306 pc.readLimit -= int64(n)
2307 return
2308 }
2309
2310
2311 func (pc *persistConn) isBroken() bool {
2312 pc.mu.Lock()
2313 b := pc.closed != nil
2314 pc.mu.Unlock()
2315 return b
2316 }
2317
2318
2319
2320 func (pc *persistConn) canceled() error {
2321 pc.mu.Lock()
2322 defer pc.mu.Unlock()
2323 return pc.canceledErr
2324 }
2325
2326
2327 func (pc *persistConn) isReused() bool {
2328 pc.mu.Lock()
2329 r := pc.reused
2330 pc.mu.Unlock()
2331 return r
2332 }
2333
2334 func (pc *persistConn) cancelRequest(err error) {
2335 pc.mu.Lock()
2336 defer pc.mu.Unlock()
2337 pc.canceledErr = err
2338 pc.closeLocked(errRequestCanceled)
2339 }
2340
2341
2342
2343
2344 func (pc *persistConn) closeConnIfStillIdle() {
2345 t := pc.t
2346 t.idleMu.Lock()
2347 defer t.idleMu.Unlock()
2348 if _, ok := t.idleLRU.m[pc]; !ok {
2349
2350 return
2351 }
2352 t.removeIdleConnLocked(pc)
2353 pc.close(errIdleConnTimeout)
2354 }
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364 func (pc *persistConn) mapRoundTripError(req *transportRequest, startBytesWritten int64, err error) error {
2365 if err == nil {
2366 return nil
2367 }
2368
2369
2370
2371
2372
2373
2374
2375
2376 <-pc.writeLoopDone
2377
2378
2379
2380
2381 if cerr := pc.canceled(); cerr != nil {
2382 return cerr
2383 }
2384
2385
2386 req.mu.Lock()
2387 reqErr := req.err
2388 req.mu.Unlock()
2389 if reqErr != nil {
2390 return reqErr
2391 }
2392
2393 if err == errServerClosedIdle {
2394
2395 return err
2396 }
2397
2398 if _, ok := err.(transportReadFromServerError); ok {
2399 if pc.nwrite == startBytesWritten {
2400 return nothingWrittenError{err}
2401 }
2402
2403 return err
2404 }
2405 if pc.isBroken() {
2406 if pc.nwrite == startBytesWritten {
2407 return nothingWrittenError{err}
2408 }
2409 return fmt.Errorf("net/http: HTTP/1.x transport connection broken: %w", err)
2410 }
2411 return err
2412 }
2413
2414
2415
2416
2417 var errCallerOwnsConn = errors.New("read loop ending; caller owns writable underlying conn")
2418
2419
2420
2421
2422 const maxPostCloseReadBytes = 256 << 10
2423
2424
2425
2426
2427 const maxPostCloseReadTime = 50 * time.Millisecond
2428
2429 func maybeDrainBody(body io.Reader) bool {
2430 drainedCh := make(chan bool, 1)
2431 go func() {
2432 if _, err := io.CopyN(io.Discard, body, maxPostCloseReadBytes+1); err == io.EOF {
2433 drainedCh <- true
2434 } else {
2435 drainedCh <- false
2436 }
2437 }()
2438 select {
2439 case drained := <-drainedCh:
2440 return drained
2441 case <-time.After(maxPostCloseReadTime):
2442 return false
2443 }
2444 }
2445
2446 func (pc *persistConn) readLoop() {
2447 closeErr := errReadLoopExiting
2448 defer func() {
2449 pc.close(closeErr)
2450 pc.t.removeIdleConn(pc)
2451 if pc.internalStateHook != nil {
2452 pc.internalStateHook()
2453 }
2454 }()
2455
2456 tryPutIdleConn := func(treq *transportRequest) bool {
2457 trace := treq.trace
2458 if err := pc.t.tryPutIdleConn(pc); err != nil {
2459 closeErr = err
2460 if trace != nil && trace.PutIdleConn != nil && err != errKeepAlivesDisabled {
2461 trace.PutIdleConn(err)
2462 }
2463 return false
2464 }
2465 if trace != nil && trace.PutIdleConn != nil {
2466 trace.PutIdleConn(nil)
2467 }
2468 return true
2469 }
2470
2471
2472
2473
2474 eofc := make(chan struct{})
2475 defer close(eofc)
2476
2477
2478 testHookMu.Lock()
2479 testHookReadLoopBeforeNextRead := testHookReadLoopBeforeNextRead
2480 testHookMu.Unlock()
2481
2482 alive := true
2483 for alive {
2484 pc.readLimit = pc.maxHeaderResponseSize()
2485 _, err := pc.br.Peek(1)
2486
2487 pc.mu.Lock()
2488 if pc.numExpectedResponses == 0 {
2489 pc.readLoopPeekFailLocked(err)
2490 pc.mu.Unlock()
2491 return
2492 }
2493 pc.mu.Unlock()
2494
2495 rc := <-pc.reqch
2496 trace := rc.treq.trace
2497
2498 var resp *Response
2499 if err == nil {
2500 resp, err = pc.readResponse(rc, trace)
2501 } else {
2502 err = transportReadFromServerError{err}
2503 closeErr = err
2504 }
2505
2506 if err != nil {
2507 if pc.readLimit <= 0 {
2508 err = fmt.Errorf("net/http: server response headers exceeded %d bytes; aborted", pc.maxHeaderResponseSize())
2509 }
2510
2511 select {
2512 case rc.ch <- responseAndError{err: err}:
2513 case <-rc.callerGone:
2514 return
2515 }
2516 return
2517 }
2518 pc.readLimit = maxInt64
2519
2520 pc.mu.Lock()
2521 pc.numExpectedResponses--
2522 pc.mu.Unlock()
2523
2524 bodyWritable := resp.bodyIsWritable()
2525 hasBody := rc.treq.Request.Method != "HEAD" && resp.ContentLength != 0
2526
2527 if resp.Close || rc.treq.Request.Close || resp.StatusCode <= 199 || bodyWritable {
2528
2529
2530
2531 alive = false
2532 }
2533
2534 if !hasBody || bodyWritable {
2535
2536
2537
2538
2539
2540 alive = alive &&
2541 !pc.sawEOF &&
2542 pc.wroteRequest() &&
2543 tryPutIdleConn(rc.treq)
2544
2545 if bodyWritable {
2546 closeErr = errCallerOwnsConn
2547 }
2548
2549 select {
2550 case rc.ch <- responseAndError{res: resp}:
2551 case <-rc.callerGone:
2552 return
2553 }
2554
2555 rc.treq.cancel(errRequestDone)
2556
2557
2558
2559
2560 testHookReadLoopBeforeNextRead()
2561 continue
2562 }
2563
2564 waitForBodyRead := make(chan bool, 2)
2565 body := &bodyEOFSignal{
2566 body: resp.Body,
2567 earlyCloseFn: func() error {
2568 waitForBodyRead <- false
2569 <-eofc
2570 return nil
2571
2572 },
2573 fn: func(err error) error {
2574 isEOF := err == io.EOF
2575 waitForBodyRead <- isEOF
2576 if isEOF {
2577 <-eofc
2578 } else if err != nil {
2579 if cerr := pc.canceled(); cerr != nil {
2580 return cerr
2581 }
2582 }
2583 return err
2584 },
2585 }
2586
2587 resp.Body = body
2588 if rc.addedGzip && ascii.EqualFold(resp.Header.Get("Content-Encoding"), "gzip") {
2589 resp.Body = &gzipReader{body: body}
2590 resp.Header.Del("Content-Encoding")
2591 resp.Header.Del("Content-Length")
2592 resp.ContentLength = -1
2593 resp.Uncompressed = true
2594 }
2595
2596 select {
2597 case rc.ch <- responseAndError{res: resp}:
2598 case <-rc.callerGone:
2599 return
2600 }
2601
2602
2603
2604
2605 select {
2606 case bodyEOF := <-waitForBodyRead:
2607 tryDrain := !bodyEOF && resp.ContentLength <= maxPostCloseReadBytes
2608 if tryDrain {
2609 eofc <- struct{}{}
2610 bodyEOF = maybeDrainBody(body.body)
2611 }
2612 alive = alive &&
2613 bodyEOF &&
2614 !pc.sawEOF &&
2615 pc.wroteRequest() &&
2616 tryPutIdleConn(rc.treq)
2617 if !tryDrain && bodyEOF {
2618 eofc <- struct{}{}
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 {
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 var errConcurrentReadOnResBody = errors.New("http: concurrent read on response body")
3228
3229 func (es *bodyEOFSignal) Read(p []byte) (n int, err error) {
3230 es.mu.Lock()
3231 closed, rerr := es.closed, es.rerr
3232 es.mu.Unlock()
3233 if closed {
3234 return 0, errReadOnClosedResBody
3235 }
3236 if rerr != nil {
3237 return 0, rerr
3238 }
3239
3240 n, err = es.body.Read(p)
3241 if err != nil {
3242 es.mu.Lock()
3243 defer es.mu.Unlock()
3244 if es.rerr == nil {
3245 es.rerr = err
3246 }
3247 err = es.condfn(err)
3248 }
3249 return
3250 }
3251
3252 func (es *bodyEOFSignal) Close() error {
3253 es.mu.Lock()
3254 defer es.mu.Unlock()
3255 if es.closed {
3256 return nil
3257 }
3258 es.closed = true
3259 if es.earlyCloseFn != nil && es.rerr != io.EOF {
3260 return es.earlyCloseFn()
3261 }
3262 err := es.body.Close()
3263 return es.condfn(err)
3264 }
3265
3266
3267 func (es *bodyEOFSignal) condfn(err error) error {
3268 if es.fn == nil {
3269 return err
3270 }
3271 err = es.fn(err)
3272 es.fn = nil
3273 return err
3274 }
3275
3276
3277
3278
3279
3280 type gzipReader struct {
3281 _ incomparable
3282 body *bodyEOFSignal
3283 mu sync.Mutex
3284 zr *gzip.Reader
3285 zerr error
3286 }
3287
3288 type eofReader struct{}
3289
3290 func (eofReader) Read([]byte) (int, error) { return 0, io.EOF }
3291 func (eofReader) ReadByte() (byte, error) { return 0, io.EOF }
3292
3293 var gzipPool = sync.Pool{New: func() any { return new(gzip.Reader) }}
3294
3295
3296 func gzipPoolGet(r io.Reader) (*gzip.Reader, error) {
3297 zr := gzipPool.Get().(*gzip.Reader)
3298 if err := zr.Reset(r); err != nil {
3299 gzipPoolPut(zr)
3300 return nil, err
3301 }
3302 return zr, nil
3303 }
3304
3305
3306 func gzipPoolPut(zr *gzip.Reader) {
3307
3308
3309 var r flate.Reader = eofReader{}
3310 zr.Reset(r)
3311 gzipPool.Put(zr)
3312 }
3313
3314
3315
3316 func (gz *gzipReader) acquire() (*gzip.Reader, error) {
3317 gz.mu.Lock()
3318 defer gz.mu.Unlock()
3319 if gz.zerr != nil {
3320 return nil, gz.zerr
3321 }
3322 if gz.zr == nil {
3323
3324
3325
3326
3327 gz.zerr = errConcurrentReadOnResBody
3328 gz.mu.Unlock()
3329 zr, err := gzipPoolGet(gz.body)
3330 gz.mu.Lock()
3331
3332 if gz.zerr != errConcurrentReadOnResBody {
3333 if zr != nil {
3334 gzipPoolPut(zr)
3335 }
3336 return nil, gz.zerr
3337 }
3338 gz.zr, gz.zerr = zr, err
3339 if gz.zerr != nil {
3340 return nil, gz.zerr
3341 }
3342 }
3343 ret := gz.zr
3344 gz.zr, gz.zerr = nil, errConcurrentReadOnResBody
3345 return ret, nil
3346 }
3347
3348
3349 func (gz *gzipReader) release(zr *gzip.Reader) {
3350 gz.mu.Lock()
3351 defer gz.mu.Unlock()
3352 if gz.zerr == errConcurrentReadOnResBody {
3353 gz.zr, gz.zerr = zr, nil
3354 } else {
3355 gzipPoolPut(zr)
3356 }
3357 }
3358
3359
3360
3361 func (gz *gzipReader) close() {
3362 gz.mu.Lock()
3363 defer gz.mu.Unlock()
3364 if gz.zerr == nil && gz.zr != nil {
3365 gzipPoolPut(gz.zr)
3366 gz.zr = nil
3367 }
3368 gz.zerr = errReadOnClosedResBody
3369 }
3370
3371 func (gz *gzipReader) Read(p []byte) (n int, err error) {
3372 zr, err := gz.acquire()
3373 if err != nil {
3374 return 0, err
3375 }
3376 defer gz.release(zr)
3377
3378 return zr.Read(p)
3379 }
3380
3381 func (gz *gzipReader) Close() error {
3382 gz.close()
3383
3384 return gz.body.Close()
3385 }
3386
3387 type tlsHandshakeTimeoutError struct{}
3388
3389 func (tlsHandshakeTimeoutError) Timeout() bool { return true }
3390 func (tlsHandshakeTimeoutError) Temporary() bool { return true }
3391 func (tlsHandshakeTimeoutError) Error() string { return "net/http: TLS handshake timeout" }
3392
3393
3394
3395
3396 type fakeLocker struct{}
3397
3398 func (fakeLocker) Lock() {}
3399 func (fakeLocker) Unlock() {}
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414 func cloneTLSConfig(cfg *tls.Config) *tls.Config {
3415 if cfg == nil {
3416 return &tls.Config{}
3417 }
3418 return cfg.Clone()
3419 }
3420
3421 type connLRU struct {
3422 ll *list.List
3423 m map[*persistConn]*list.Element
3424 }
3425
3426
3427 func (cl *connLRU) add(pc *persistConn) {
3428 if cl.ll == nil {
3429 cl.ll = list.New()
3430 cl.m = make(map[*persistConn]*list.Element)
3431 }
3432 ele := cl.ll.PushFront(pc)
3433 if _, ok := cl.m[pc]; ok {
3434 panic("persistConn was already in LRU")
3435 }
3436 cl.m[pc] = ele
3437 }
3438
3439 func (cl *connLRU) removeOldest() *persistConn {
3440 ele := cl.ll.Back()
3441 pc := ele.Value.(*persistConn)
3442 cl.ll.Remove(ele)
3443 delete(cl.m, pc)
3444 return pc
3445 }
3446
3447
3448 func (cl *connLRU) remove(pc *persistConn) {
3449 if ele, ok := cl.m[pc]; ok {
3450 cl.ll.Remove(ele)
3451 delete(cl.m, pc)
3452 }
3453 }
3454
3455
3456 func (cl *connLRU) len() int {
3457 return len(cl.m)
3458 }
3459
View as plain text