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