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