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