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 return nil, fmt.Errorf("net/http: invalid header field value %q for key %v", v, k)
529 }
530 }
531 }
532 }
533
534 origReq := req
535 cancelKey := cancelKey{origReq}
536 req = setupRewindBody(req)
537
538 if altRT := t.alternateRoundTripper(req); altRT != nil {
539 if resp, err := altRT.RoundTrip(req); err != ErrSkipAltProtocol {
540 return resp, err
541 }
542 var err error
543 req, err = rewindBody(req)
544 if err != nil {
545 return nil, err
546 }
547 }
548 if !isHTTP {
549 req.closeBody()
550 return nil, badStringError("unsupported protocol scheme", scheme)
551 }
552 if req.Method != "" && !validMethod(req.Method) {
553 req.closeBody()
554 return nil, fmt.Errorf("net/http: invalid method %q", req.Method)
555 }
556 if req.URL.Host == "" {
557 req.closeBody()
558 return nil, errors.New("http: no Host in request URL")
559 }
560
561 for {
562 select {
563 case <-ctx.Done():
564 req.closeBody()
565 return nil, ctx.Err()
566 default:
567 }
568
569
570 treq := &transportRequest{Request: req, trace: trace, cancelKey: cancelKey}
571 cm, err := t.connectMethodForRequest(treq)
572 if err != nil {
573 req.closeBody()
574 return nil, err
575 }
576
577
578
579
580
581 pconn, err := t.getConn(treq, cm)
582 if err != nil {
583 t.setReqCanceler(cancelKey, nil)
584 req.closeBody()
585 return nil, err
586 }
587
588 var resp *Response
589 if pconn.alt != nil {
590
591 t.setReqCanceler(cancelKey, nil)
592 resp, err = pconn.alt.RoundTrip(req)
593 } else {
594 resp, err = pconn.roundTrip(treq)
595 }
596 if err == nil {
597 resp.Request = origReq
598 return resp, nil
599 }
600
601
602 if http2isNoCachedConnError(err) {
603 if t.removeIdleConn(pconn) {
604 t.decConnsPerHost(pconn.cacheKey)
605 }
606 } else if !pconn.shouldRetryRequest(req, err) {
607
608
609 if e, ok := err.(nothingWrittenError); ok {
610 err = e.error
611 }
612 if e, ok := err.(transportReadFromServerError); ok {
613 err = e.err
614 }
615 return nil, err
616 }
617 testHookRoundTripRetried()
618
619
620 req, err = rewindBody(req)
621 if err != nil {
622 return nil, err
623 }
624 }
625 }
626
627 var errCannotRewind = errors.New("net/http: cannot rewind body after connection loss")
628
629 type readTrackingBody struct {
630 io.ReadCloser
631 didRead bool
632 didClose bool
633 }
634
635 func (r *readTrackingBody) Read(data []byte) (int, error) {
636 r.didRead = true
637 return r.ReadCloser.Read(data)
638 }
639
640 func (r *readTrackingBody) Close() error {
641 r.didClose = true
642 return r.ReadCloser.Close()
643 }
644
645
646
647
648
649 func setupRewindBody(req *Request) *Request {
650 if req.Body == nil || req.Body == NoBody {
651 return req
652 }
653 newReq := *req
654 newReq.Body = &readTrackingBody{ReadCloser: req.Body}
655 return &newReq
656 }
657
658
659
660
661
662 func rewindBody(req *Request) (rewound *Request, err error) {
663 if req.Body == nil || req.Body == NoBody || (!req.Body.(*readTrackingBody).didRead && !req.Body.(*readTrackingBody).didClose) {
664 return req, nil
665 }
666 if !req.Body.(*readTrackingBody).didClose {
667 req.closeBody()
668 }
669 if req.GetBody == nil {
670 return nil, errCannotRewind
671 }
672 body, err := req.GetBody()
673 if err != nil {
674 return nil, err
675 }
676 newReq := *req
677 newReq.Body = &readTrackingBody{ReadCloser: body}
678 return &newReq, nil
679 }
680
681
682
683
684 func (pc *persistConn) shouldRetryRequest(req *Request, err error) bool {
685 if http2isNoCachedConnError(err) {
686
687
688
689
690
691
692 return true
693 }
694 if err == errMissingHost {
695
696 return false
697 }
698 if !pc.isReused() {
699
700
701
702
703
704
705
706 return false
707 }
708 if _, ok := err.(nothingWrittenError); ok {
709
710
711 return req.outgoingLength() == 0 || req.GetBody != nil
712 }
713 if !req.isReplayable() {
714
715 return false
716 }
717 if _, ok := err.(transportReadFromServerError); ok {
718
719
720 return true
721 }
722 if err == errServerClosedIdle {
723
724
725
726 return true
727 }
728 return false
729 }
730
731
732 var ErrSkipAltProtocol = errors.New("net/http: skip alternate protocol")
733
734
735
736
737
738
739
740
741
742
743
744 func (t *Transport) RegisterProtocol(scheme string, rt RoundTripper) {
745 t.altMu.Lock()
746 defer t.altMu.Unlock()
747 oldMap, _ := t.altProto.Load().(map[string]RoundTripper)
748 if _, exists := oldMap[scheme]; exists {
749 panic("protocol " + scheme + " already registered")
750 }
751 newMap := make(map[string]RoundTripper)
752 for k, v := range oldMap {
753 newMap[k] = v
754 }
755 newMap[scheme] = rt
756 t.altProto.Store(newMap)
757 }
758
759
760
761
762
763 func (t *Transport) CloseIdleConnections() {
764 t.nextProtoOnce.Do(t.onceSetNextProtoDefaults)
765 t.idleMu.Lock()
766 m := t.idleConn
767 t.idleConn = nil
768 t.closeIdle = true
769 t.idleLRU = connLRU{}
770 t.idleMu.Unlock()
771 for _, conns := range m {
772 for _, pconn := range conns {
773 pconn.close(errCloseIdleConns)
774 }
775 }
776 if t2 := t.h2transport; t2 != nil {
777 t2.CloseIdleConnections()
778 }
779 }
780
781
782
783
784
785
786
787 func (t *Transport) CancelRequest(req *Request) {
788 t.cancelRequest(cancelKey{req}, errRequestCanceled)
789 }
790
791
792
793 func (t *Transport) cancelRequest(key cancelKey, err error) bool {
794
795
796 t.reqMu.Lock()
797 defer t.reqMu.Unlock()
798 cancel := t.reqCanceler[key]
799 delete(t.reqCanceler, key)
800 if cancel != nil {
801 cancel(err)
802 }
803
804 return cancel != nil
805 }
806
807
808
809
810
811 var (
812
813 envProxyOnce sync.Once
814 envProxyFuncValue func(*url.URL) (*url.URL, error)
815 )
816
817
818
819
820 func envProxyFunc() func(*url.URL) (*url.URL, error) {
821 envProxyOnce.Do(func() {
822 envProxyFuncValue = httpproxy.FromEnvironment().ProxyFunc()
823 })
824 return envProxyFuncValue
825 }
826
827
828 func resetProxyConfig() {
829 envProxyOnce = sync.Once{}
830 envProxyFuncValue = nil
831 }
832
833 func (t *Transport) connectMethodForRequest(treq *transportRequest) (cm connectMethod, err error) {
834 cm.targetScheme = treq.URL.Scheme
835 cm.targetAddr = canonicalAddr(treq.URL)
836 if t.Proxy != nil {
837 cm.proxyURL, err = t.Proxy(treq.Request)
838 }
839 cm.onlyH1 = treq.requiresHTTP1()
840 return cm, err
841 }
842
843
844
845 func (cm *connectMethod) proxyAuth() string {
846 if cm.proxyURL == nil {
847 return ""
848 }
849 if u := cm.proxyURL.User; u != nil {
850 username := u.Username()
851 password, _ := u.Password()
852 return "Basic " + basicAuth(username, password)
853 }
854 return ""
855 }
856
857
858 var (
859 errKeepAlivesDisabled = errors.New("http: putIdleConn: keep alives disabled")
860 errConnBroken = errors.New("http: putIdleConn: connection is in bad state")
861 errCloseIdle = errors.New("http: putIdleConn: CloseIdleConnections was called")
862 errTooManyIdle = errors.New("http: putIdleConn: too many idle connections")
863 errTooManyIdleHost = errors.New("http: putIdleConn: too many idle connections for host")
864 errCloseIdleConns = errors.New("http: CloseIdleConnections called")
865 errReadLoopExiting = errors.New("http: persistConn.readLoop exiting")
866 errIdleConnTimeout = errors.New("http: idle connection timeout")
867
868
869
870
871
872 errServerClosedIdle = errors.New("http: server closed idle connection")
873 )
874
875
876
877
878
879
880
881
882
883 type transportReadFromServerError struct {
884 err error
885 }
886
887 func (e transportReadFromServerError) Unwrap() error { return e.err }
888
889 func (e transportReadFromServerError) Error() string {
890 return fmt.Sprintf("net/http: Transport failed to read from server: %v", e.err)
891 }
892
893 func (t *Transport) putOrCloseIdleConn(pconn *persistConn) {
894 if err := t.tryPutIdleConn(pconn); err != nil {
895 pconn.close(err)
896 }
897 }
898
899 func (t *Transport) maxIdleConnsPerHost() int {
900 if v := t.MaxIdleConnsPerHost; v != 0 {
901 return v
902 }
903 return DefaultMaxIdleConnsPerHost
904 }
905
906
907
908
909
910
911 func (t *Transport) tryPutIdleConn(pconn *persistConn) error {
912 if t.DisableKeepAlives || t.MaxIdleConnsPerHost < 0 {
913 return errKeepAlivesDisabled
914 }
915 if pconn.isBroken() {
916 return errConnBroken
917 }
918 pconn.markReused()
919
920 t.idleMu.Lock()
921 defer t.idleMu.Unlock()
922
923
924
925
926 if pconn.alt != nil && t.idleLRU.m[pconn] != nil {
927 return nil
928 }
929
930
931
932
933
934 key := pconn.cacheKey
935 if q, ok := t.idleConnWait[key]; ok {
936 done := false
937 if pconn.alt == nil {
938
939
940 for q.len() > 0 {
941 w := q.popFront()
942 if w.tryDeliver(pconn, nil) {
943 done = true
944 break
945 }
946 }
947 } else {
948
949
950
951
952 for q.len() > 0 {
953 w := q.popFront()
954 w.tryDeliver(pconn, nil)
955 }
956 }
957 if q.len() == 0 {
958 delete(t.idleConnWait, key)
959 } else {
960 t.idleConnWait[key] = q
961 }
962 if done {
963 return nil
964 }
965 }
966
967 if t.closeIdle {
968 return errCloseIdle
969 }
970 if t.idleConn == nil {
971 t.idleConn = make(map[connectMethodKey][]*persistConn)
972 }
973 idles := t.idleConn[key]
974 if len(idles) >= t.maxIdleConnsPerHost() {
975 return errTooManyIdleHost
976 }
977 for _, exist := range idles {
978 if exist == pconn {
979 log.Fatalf("dup idle pconn %p in freelist", pconn)
980 }
981 }
982 t.idleConn[key] = append(idles, pconn)
983 t.idleLRU.add(pconn)
984 if t.MaxIdleConns != 0 && t.idleLRU.len() > t.MaxIdleConns {
985 oldest := t.idleLRU.removeOldest()
986 oldest.close(errTooManyIdle)
987 t.removeIdleConnLocked(oldest)
988 }
989
990
991
992
993 if t.IdleConnTimeout > 0 && pconn.alt == nil {
994 if pconn.idleTimer != nil {
995 pconn.idleTimer.Reset(t.IdleConnTimeout)
996 } else {
997 pconn.idleTimer = time.AfterFunc(t.IdleConnTimeout, pconn.closeConnIfStillIdle)
998 }
999 }
1000 pconn.idleAt = time.Now()
1001 return nil
1002 }
1003
1004
1005
1006
1007 func (t *Transport) queueForIdleConn(w *wantConn) (delivered bool) {
1008 if t.DisableKeepAlives {
1009 return false
1010 }
1011
1012 t.idleMu.Lock()
1013 defer t.idleMu.Unlock()
1014
1015
1016
1017 t.closeIdle = false
1018
1019 if w == nil {
1020
1021 return false
1022 }
1023
1024
1025
1026
1027 var oldTime time.Time
1028 if t.IdleConnTimeout > 0 {
1029 oldTime = time.Now().Add(-t.IdleConnTimeout)
1030 }
1031
1032
1033 if list, ok := t.idleConn[w.key]; ok {
1034 stop := false
1035 delivered := false
1036 for len(list) > 0 && !stop {
1037 pconn := list[len(list)-1]
1038
1039
1040
1041
1042 tooOld := !oldTime.IsZero() && pconn.idleAt.Round(0).Before(oldTime)
1043 if tooOld {
1044
1045
1046
1047 go pconn.closeConnIfStillIdle()
1048 }
1049 if pconn.isBroken() || tooOld {
1050
1051
1052
1053
1054
1055 list = list[:len(list)-1]
1056 continue
1057 }
1058 delivered = w.tryDeliver(pconn, nil)
1059 if delivered {
1060 if pconn.alt != nil {
1061
1062
1063 } else {
1064
1065
1066 t.idleLRU.remove(pconn)
1067 list = list[:len(list)-1]
1068 }
1069 }
1070 stop = true
1071 }
1072 if len(list) > 0 {
1073 t.idleConn[w.key] = list
1074 } else {
1075 delete(t.idleConn, w.key)
1076 }
1077 if stop {
1078 return delivered
1079 }
1080 }
1081
1082
1083 if t.idleConnWait == nil {
1084 t.idleConnWait = make(map[connectMethodKey]wantConnQueue)
1085 }
1086 q := t.idleConnWait[w.key]
1087 q.cleanFront()
1088 q.pushBack(w)
1089 t.idleConnWait[w.key] = q
1090 return false
1091 }
1092
1093
1094 func (t *Transport) removeIdleConn(pconn *persistConn) bool {
1095 t.idleMu.Lock()
1096 defer t.idleMu.Unlock()
1097 return t.removeIdleConnLocked(pconn)
1098 }
1099
1100
1101 func (t *Transport) removeIdleConnLocked(pconn *persistConn) bool {
1102 if pconn.idleTimer != nil {
1103 pconn.idleTimer.Stop()
1104 }
1105 t.idleLRU.remove(pconn)
1106 key := pconn.cacheKey
1107 pconns := t.idleConn[key]
1108 var removed bool
1109 switch len(pconns) {
1110 case 0:
1111
1112 case 1:
1113 if pconns[0] == pconn {
1114 delete(t.idleConn, key)
1115 removed = true
1116 }
1117 default:
1118 for i, v := range pconns {
1119 if v != pconn {
1120 continue
1121 }
1122
1123
1124 copy(pconns[i:], pconns[i+1:])
1125 t.idleConn[key] = pconns[:len(pconns)-1]
1126 removed = true
1127 break
1128 }
1129 }
1130 return removed
1131 }
1132
1133 func (t *Transport) setReqCanceler(key cancelKey, fn func(error)) {
1134 t.reqMu.Lock()
1135 defer t.reqMu.Unlock()
1136 if t.reqCanceler == nil {
1137 t.reqCanceler = make(map[cancelKey]func(error))
1138 }
1139 if fn != nil {
1140 t.reqCanceler[key] = fn
1141 } else {
1142 delete(t.reqCanceler, key)
1143 }
1144 }
1145
1146
1147
1148
1149
1150 func (t *Transport) replaceReqCanceler(key cancelKey, fn func(error)) bool {
1151 t.reqMu.Lock()
1152 defer t.reqMu.Unlock()
1153 _, ok := t.reqCanceler[key]
1154 if !ok {
1155 return false
1156 }
1157 if fn != nil {
1158 t.reqCanceler[key] = fn
1159 } else {
1160 delete(t.reqCanceler, key)
1161 }
1162 return true
1163 }
1164
1165 var zeroDialer net.Dialer
1166
1167 func (t *Transport) dial(ctx context.Context, network, addr string) (net.Conn, error) {
1168 if t.DialContext != nil {
1169 return t.DialContext(ctx, network, addr)
1170 }
1171 if t.Dial != nil {
1172 c, err := t.Dial(network, addr)
1173 if c == nil && err == nil {
1174 err = errors.New("net/http: Transport.Dial hook returned (nil, nil)")
1175 }
1176 return c, err
1177 }
1178 return zeroDialer.DialContext(ctx, network, addr)
1179 }
1180
1181
1182
1183
1184
1185
1186
1187 type wantConn struct {
1188 cm connectMethod
1189 key connectMethodKey
1190 ctx context.Context
1191 ready chan struct{}
1192
1193
1194
1195
1196 beforeDial func()
1197 afterDial func()
1198
1199 mu sync.Mutex
1200 pc *persistConn
1201 err error
1202 }
1203
1204
1205 func (w *wantConn) waiting() bool {
1206 select {
1207 case <-w.ready:
1208 return false
1209 default:
1210 return true
1211 }
1212 }
1213
1214
1215 func (w *wantConn) tryDeliver(pc *persistConn, err error) bool {
1216 w.mu.Lock()
1217 defer w.mu.Unlock()
1218
1219 if w.pc != nil || w.err != nil {
1220 return false
1221 }
1222
1223 w.pc = pc
1224 w.err = err
1225 if w.pc == nil && w.err == nil {
1226 panic("net/http: internal error: misuse of tryDeliver")
1227 }
1228 close(w.ready)
1229 return true
1230 }
1231
1232
1233
1234 func (w *wantConn) cancel(t *Transport, err error) {
1235 w.mu.Lock()
1236 if w.pc == nil && w.err == nil {
1237 close(w.ready)
1238 }
1239 pc := w.pc
1240 w.pc = nil
1241 w.err = err
1242 w.mu.Unlock()
1243
1244 if pc != nil {
1245 t.putOrCloseIdleConn(pc)
1246 }
1247 }
1248
1249
1250 type wantConnQueue struct {
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261 head []*wantConn
1262 headPos int
1263 tail []*wantConn
1264 }
1265
1266
1267 func (q *wantConnQueue) len() int {
1268 return len(q.head) - q.headPos + len(q.tail)
1269 }
1270
1271
1272 func (q *wantConnQueue) pushBack(w *wantConn) {
1273 q.tail = append(q.tail, w)
1274 }
1275
1276
1277 func (q *wantConnQueue) popFront() *wantConn {
1278 if q.headPos >= len(q.head) {
1279 if len(q.tail) == 0 {
1280 return nil
1281 }
1282
1283 q.head, q.headPos, q.tail = q.tail, 0, q.head[:0]
1284 }
1285 w := q.head[q.headPos]
1286 q.head[q.headPos] = nil
1287 q.headPos++
1288 return w
1289 }
1290
1291
1292 func (q *wantConnQueue) peekFront() *wantConn {
1293 if q.headPos < len(q.head) {
1294 return q.head[q.headPos]
1295 }
1296 if len(q.tail) > 0 {
1297 return q.tail[0]
1298 }
1299 return nil
1300 }
1301
1302
1303
1304 func (q *wantConnQueue) cleanFront() (cleaned bool) {
1305 for {
1306 w := q.peekFront()
1307 if w == nil || w.waiting() {
1308 return cleaned
1309 }
1310 q.popFront()
1311 cleaned = true
1312 }
1313 }
1314
1315 func (t *Transport) customDialTLS(ctx context.Context, network, addr string) (conn net.Conn, err error) {
1316 if t.DialTLSContext != nil {
1317 conn, err = t.DialTLSContext(ctx, network, addr)
1318 } else {
1319 conn, err = t.DialTLS(network, addr)
1320 }
1321 if conn == nil && err == nil {
1322 err = errors.New("net/http: Transport.DialTLS or DialTLSContext returned (nil, nil)")
1323 }
1324 return
1325 }
1326
1327
1328
1329
1330
1331 func (t *Transport) getConn(treq *transportRequest, cm connectMethod) (pc *persistConn, err error) {
1332 req := treq.Request
1333 trace := treq.trace
1334 ctx := req.Context()
1335 if trace != nil && trace.GetConn != nil {
1336 trace.GetConn(cm.addr())
1337 }
1338
1339 w := &wantConn{
1340 cm: cm,
1341 key: cm.key(),
1342 ctx: ctx,
1343 ready: make(chan struct{}, 1),
1344 beforeDial: testHookPrePendingDial,
1345 afterDial: testHookPostPendingDial,
1346 }
1347 defer func() {
1348 if err != nil {
1349 w.cancel(t, err)
1350 }
1351 }()
1352
1353
1354 if delivered := t.queueForIdleConn(w); delivered {
1355 pc := w.pc
1356
1357
1358 if pc.alt == nil && trace != nil && trace.GotConn != nil {
1359 trace.GotConn(pc.gotIdleConnTrace(pc.idleAt))
1360 }
1361
1362
1363
1364 t.setReqCanceler(treq.cancelKey, func(error) {})
1365 return pc, nil
1366 }
1367
1368 cancelc := make(chan error, 1)
1369 t.setReqCanceler(treq.cancelKey, func(err error) { cancelc <- err })
1370
1371
1372 t.queueForDial(w)
1373
1374
1375 select {
1376 case <-w.ready:
1377
1378
1379 if w.pc != nil && w.pc.alt == nil && trace != nil && trace.GotConn != nil {
1380 trace.GotConn(httptrace.GotConnInfo{Conn: w.pc.conn, Reused: w.pc.isReused()})
1381 }
1382 if w.err != nil {
1383
1384
1385
1386 select {
1387 case <-req.Cancel:
1388 return nil, errRequestCanceledConn
1389 case <-req.Context().Done():
1390 return nil, req.Context().Err()
1391 case err := <-cancelc:
1392 if err == errRequestCanceled {
1393 err = errRequestCanceledConn
1394 }
1395 return nil, err
1396 default:
1397
1398 }
1399 }
1400 return w.pc, w.err
1401 case <-req.Cancel:
1402 return nil, errRequestCanceledConn
1403 case <-req.Context().Done():
1404 return nil, req.Context().Err()
1405 case err := <-cancelc:
1406 if err == errRequestCanceled {
1407 err = errRequestCanceledConn
1408 }
1409 return nil, err
1410 }
1411 }
1412
1413
1414
1415 func (t *Transport) queueForDial(w *wantConn) {
1416 w.beforeDial()
1417 if t.MaxConnsPerHost <= 0 {
1418 go t.dialConnFor(w)
1419 return
1420 }
1421
1422 t.connsPerHostMu.Lock()
1423 defer t.connsPerHostMu.Unlock()
1424
1425 if n := t.connsPerHost[w.key]; n < t.MaxConnsPerHost {
1426 if t.connsPerHost == nil {
1427 t.connsPerHost = make(map[connectMethodKey]int)
1428 }
1429 t.connsPerHost[w.key] = n + 1
1430 go t.dialConnFor(w)
1431 return
1432 }
1433
1434 if t.connsPerHostWait == nil {
1435 t.connsPerHostWait = make(map[connectMethodKey]wantConnQueue)
1436 }
1437 q := t.connsPerHostWait[w.key]
1438 q.cleanFront()
1439 q.pushBack(w)
1440 t.connsPerHostWait[w.key] = q
1441 }
1442
1443
1444
1445
1446 func (t *Transport) dialConnFor(w *wantConn) {
1447 defer w.afterDial()
1448
1449 pc, err := t.dialConn(w.ctx, w.cm)
1450 delivered := w.tryDeliver(pc, err)
1451 if err == nil && (!delivered || pc.alt != nil) {
1452
1453
1454
1455 t.putOrCloseIdleConn(pc)
1456 }
1457 if err != nil {
1458 t.decConnsPerHost(w.key)
1459 }
1460 }
1461
1462
1463
1464 func (t *Transport) decConnsPerHost(key connectMethodKey) {
1465 if t.MaxConnsPerHost <= 0 {
1466 return
1467 }
1468
1469 t.connsPerHostMu.Lock()
1470 defer t.connsPerHostMu.Unlock()
1471 n := t.connsPerHost[key]
1472 if n == 0 {
1473
1474
1475 panic("net/http: internal error: connCount underflow")
1476 }
1477
1478
1479
1480
1481
1482 if q := t.connsPerHostWait[key]; q.len() > 0 {
1483 done := false
1484 for q.len() > 0 {
1485 w := q.popFront()
1486 if w.waiting() {
1487 go t.dialConnFor(w)
1488 done = true
1489 break
1490 }
1491 }
1492 if q.len() == 0 {
1493 delete(t.connsPerHostWait, key)
1494 } else {
1495
1496
1497 t.connsPerHostWait[key] = q
1498 }
1499 if done {
1500 return
1501 }
1502 }
1503
1504
1505 if n--; n == 0 {
1506 delete(t.connsPerHost, key)
1507 } else {
1508 t.connsPerHost[key] = n
1509 }
1510 }
1511
1512
1513
1514
1515 func (pconn *persistConn) addTLS(ctx context.Context, name string, trace *httptrace.ClientTrace) error {
1516
1517 cfg := cloneTLSConfig(pconn.t.TLSClientConfig)
1518 if cfg.ServerName == "" {
1519 cfg.ServerName = name
1520 }
1521 if pconn.cacheKey.onlyH1 {
1522 cfg.NextProtos = nil
1523 }
1524 plainConn := pconn.conn
1525 tlsConn := tls.Client(plainConn, cfg)
1526 errc := make(chan error, 2)
1527 var timer *time.Timer
1528 if d := pconn.t.TLSHandshakeTimeout; d != 0 {
1529 timer = time.AfterFunc(d, func() {
1530 errc <- tlsHandshakeTimeoutError{}
1531 })
1532 }
1533 go func() {
1534 if trace != nil && trace.TLSHandshakeStart != nil {
1535 trace.TLSHandshakeStart()
1536 }
1537 err := tlsConn.HandshakeContext(ctx)
1538 if timer != nil {
1539 timer.Stop()
1540 }
1541 errc <- err
1542 }()
1543 if err := <-errc; err != nil {
1544 plainConn.Close()
1545 if trace != nil && trace.TLSHandshakeDone != nil {
1546 trace.TLSHandshakeDone(tls.ConnectionState{}, err)
1547 }
1548 return err
1549 }
1550 cs := tlsConn.ConnectionState()
1551 if trace != nil && trace.TLSHandshakeDone != nil {
1552 trace.TLSHandshakeDone(cs, nil)
1553 }
1554 pconn.tlsState = &cs
1555 pconn.conn = tlsConn
1556 return nil
1557 }
1558
1559 type erringRoundTripper interface {
1560 RoundTripErr() error
1561 }
1562
1563 func (t *Transport) dialConn(ctx context.Context, cm connectMethod) (pconn *persistConn, err error) {
1564 pconn = &persistConn{
1565 t: t,
1566 cacheKey: cm.key(),
1567 reqch: make(chan requestAndChan, 1),
1568 writech: make(chan writeRequest, 1),
1569 closech: make(chan struct{}),
1570 writeErrCh: make(chan error, 1),
1571 writeLoopDone: make(chan struct{}),
1572 }
1573 trace := httptrace.ContextClientTrace(ctx)
1574 wrapErr := func(err error) error {
1575 if cm.proxyURL != nil {
1576
1577 return &net.OpError{Op: "proxyconnect", Net: "tcp", Err: err}
1578 }
1579 return err
1580 }
1581 if cm.scheme() == "https" && t.hasCustomTLSDialer() {
1582 var err error
1583 pconn.conn, err = t.customDialTLS(ctx, "tcp", cm.addr())
1584 if err != nil {
1585 return nil, wrapErr(err)
1586 }
1587 if tc, ok := pconn.conn.(*tls.Conn); ok {
1588
1589
1590 if trace != nil && trace.TLSHandshakeStart != nil {
1591 trace.TLSHandshakeStart()
1592 }
1593 if err := tc.HandshakeContext(ctx); err != nil {
1594 go pconn.conn.Close()
1595 if trace != nil && trace.TLSHandshakeDone != nil {
1596 trace.TLSHandshakeDone(tls.ConnectionState{}, err)
1597 }
1598 return nil, err
1599 }
1600 cs := tc.ConnectionState()
1601 if trace != nil && trace.TLSHandshakeDone != nil {
1602 trace.TLSHandshakeDone(cs, nil)
1603 }
1604 pconn.tlsState = &cs
1605 }
1606 } else {
1607 conn, err := t.dial(ctx, "tcp", cm.addr())
1608 if err != nil {
1609 return nil, wrapErr(err)
1610 }
1611 pconn.conn = conn
1612 if cm.scheme() == "https" {
1613 var firstTLSHost string
1614 if firstTLSHost, _, err = net.SplitHostPort(cm.addr()); err != nil {
1615 return nil, wrapErr(err)
1616 }
1617 if err = pconn.addTLS(ctx, firstTLSHost, trace); err != nil {
1618 return nil, wrapErr(err)
1619 }
1620 }
1621 }
1622
1623
1624 switch {
1625 case cm.proxyURL == nil:
1626
1627 case cm.proxyURL.Scheme == "socks5":
1628 conn := pconn.conn
1629 d := socksNewDialer("tcp", conn.RemoteAddr().String())
1630 if u := cm.proxyURL.User; u != nil {
1631 auth := &socksUsernamePassword{
1632 Username: u.Username(),
1633 }
1634 auth.Password, _ = u.Password()
1635 d.AuthMethods = []socksAuthMethod{
1636 socksAuthMethodNotRequired,
1637 socksAuthMethodUsernamePassword,
1638 }
1639 d.Authenticate = auth.Authenticate
1640 }
1641 if _, err := d.DialWithConn(ctx, conn, "tcp", cm.targetAddr); err != nil {
1642 conn.Close()
1643 return nil, err
1644 }
1645 case cm.targetScheme == "http":
1646 pconn.isProxy = true
1647 if pa := cm.proxyAuth(); pa != "" {
1648 pconn.mutateHeaderFunc = func(h Header) {
1649 h.Set("Proxy-Authorization", pa)
1650 }
1651 }
1652 case cm.targetScheme == "https":
1653 conn := pconn.conn
1654 var hdr Header
1655 if t.GetProxyConnectHeader != nil {
1656 var err error
1657 hdr, err = t.GetProxyConnectHeader(ctx, cm.proxyURL, cm.targetAddr)
1658 if err != nil {
1659 conn.Close()
1660 return nil, err
1661 }
1662 } else {
1663 hdr = t.ProxyConnectHeader
1664 }
1665 if hdr == nil {
1666 hdr = make(Header)
1667 }
1668 if pa := cm.proxyAuth(); pa != "" {
1669 hdr = hdr.Clone()
1670 hdr.Set("Proxy-Authorization", pa)
1671 }
1672 connectReq := &Request{
1673 Method: "CONNECT",
1674 URL: &url.URL{Opaque: cm.targetAddr},
1675 Host: cm.targetAddr,
1676 Header: hdr,
1677 }
1678
1679
1680
1681
1682
1683
1684 connectCtx := ctx
1685 if ctx.Done() == nil {
1686 newCtx, cancel := context.WithTimeout(ctx, 1*time.Minute)
1687 defer cancel()
1688 connectCtx = newCtx
1689 }
1690
1691 didReadResponse := make(chan struct{})
1692 var (
1693 resp *Response
1694 err error
1695 )
1696
1697 go func() {
1698 defer close(didReadResponse)
1699 err = connectReq.Write(conn)
1700 if err != nil {
1701 return
1702 }
1703
1704
1705 br := bufio.NewReader(conn)
1706 resp, err = ReadResponse(br, connectReq)
1707 }()
1708 select {
1709 case <-connectCtx.Done():
1710 conn.Close()
1711 <-didReadResponse
1712 return nil, connectCtx.Err()
1713 case <-didReadResponse:
1714
1715 }
1716 if err != nil {
1717 conn.Close()
1718 return nil, err
1719 }
1720 if resp.StatusCode != 200 {
1721 _, text, ok := strings.Cut(resp.Status, " ")
1722 conn.Close()
1723 if !ok {
1724 return nil, errors.New("unknown status code")
1725 }
1726 return nil, errors.New(text)
1727 }
1728 }
1729
1730 if cm.proxyURL != nil && cm.targetScheme == "https" {
1731 if err := pconn.addTLS(ctx, cm.tlsHost(), trace); err != nil {
1732 return nil, err
1733 }
1734 }
1735
1736 if s := pconn.tlsState; s != nil && s.NegotiatedProtocolIsMutual && s.NegotiatedProtocol != "" {
1737 if next, ok := t.TLSNextProto[s.NegotiatedProtocol]; ok {
1738 alt := next(cm.targetAddr, pconn.conn.(*tls.Conn))
1739 if e, ok := alt.(erringRoundTripper); ok {
1740
1741 return nil, e.RoundTripErr()
1742 }
1743 return &persistConn{t: t, cacheKey: pconn.cacheKey, alt: alt}, nil
1744 }
1745 }
1746
1747 pconn.br = bufio.NewReaderSize(pconn, t.readBufferSize())
1748 pconn.bw = bufio.NewWriterSize(persistConnWriter{pconn}, t.writeBufferSize())
1749
1750 go pconn.readLoop()
1751 go pconn.writeLoop()
1752 return pconn, nil
1753 }
1754
1755
1756
1757
1758
1759
1760
1761 type persistConnWriter struct {
1762 pc *persistConn
1763 }
1764
1765 func (w persistConnWriter) Write(p []byte) (n int, err error) {
1766 n, err = w.pc.conn.Write(p)
1767 w.pc.nwrite += int64(n)
1768 return
1769 }
1770
1771
1772
1773
1774 func (w persistConnWriter) ReadFrom(r io.Reader) (n int64, err error) {
1775 n, err = io.Copy(w.pc.conn, r)
1776 w.pc.nwrite += n
1777 return
1778 }
1779
1780 var _ io.ReaderFrom = (*persistConnWriter)(nil)
1781
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