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 && resCode == StatusContinue {
2340 if trace != nil && trace.Got100Continue != nil {
2341 trace.Got100Continue()
2342 }
2343 continueCh <- struct{}{}
2344 continueCh = nil
2345 }
2346 is1xx := 100 <= resCode && resCode <= 199
2347
2348 is1xxNonTerminal := is1xx && resCode != StatusSwitchingProtocols
2349 if is1xxNonTerminal {
2350 num1xx++
2351 if num1xx > max1xxResponses {
2352 return nil, errors.New("net/http: too many 1xx informational responses")
2353 }
2354 pc.readLimit = pc.maxHeaderResponseSize()
2355 if trace != nil && trace.Got1xxResponse != nil {
2356 if err := trace.Got1xxResponse(resCode, textproto.MIMEHeader(resp.Header)); err != nil {
2357 return nil, err
2358 }
2359 }
2360 continue
2361 }
2362 break
2363 }
2364 if resp.isProtocolSwitch() {
2365 resp.Body = newReadWriteCloserBody(pc.br, pc.conn)
2366 }
2367 if continueCh != nil {
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380 if resp.Close || rc.req.Close {
2381 close(continueCh)
2382 } else {
2383 continueCh <- struct{}{}
2384 }
2385 }
2386
2387 resp.TLS = pc.tlsState
2388 return
2389 }
2390
2391
2392
2393
2394 func (pc *persistConn) waitForContinue(continueCh <-chan struct{}) func() bool {
2395 if continueCh == nil {
2396 return nil
2397 }
2398 return func() bool {
2399 timer := time.NewTimer(pc.t.ExpectContinueTimeout)
2400 defer timer.Stop()
2401
2402 select {
2403 case _, ok := <-continueCh:
2404 return ok
2405 case <-timer.C:
2406 return true
2407 case <-pc.closech:
2408 return false
2409 }
2410 }
2411 }
2412
2413 func newReadWriteCloserBody(br *bufio.Reader, rwc io.ReadWriteCloser) io.ReadWriteCloser {
2414 body := &readWriteCloserBody{ReadWriteCloser: rwc}
2415 if br.Buffered() != 0 {
2416 body.br = br
2417 }
2418 return body
2419 }
2420
2421
2422
2423
2424
2425
2426 type readWriteCloserBody struct {
2427 _ incomparable
2428 br *bufio.Reader
2429 io.ReadWriteCloser
2430 }
2431
2432 func (b *readWriteCloserBody) Read(p []byte) (n int, err error) {
2433 if b.br != nil {
2434 if n := b.br.Buffered(); len(p) > n {
2435 p = p[:n]
2436 }
2437 n, err = b.br.Read(p)
2438 if b.br.Buffered() == 0 {
2439 b.br = nil
2440 }
2441 return n, err
2442 }
2443 return b.ReadWriteCloser.Read(p)
2444 }
2445
2446
2447 type nothingWrittenError struct {
2448 error
2449 }
2450
2451 func (nwe nothingWrittenError) Unwrap() error {
2452 return nwe.error
2453 }
2454
2455 func (pc *persistConn) writeLoop() {
2456 defer close(pc.writeLoopDone)
2457 for {
2458 select {
2459 case wr := <-pc.writech:
2460 startBytesWritten := pc.nwrite
2461 err := wr.req.Request.write(pc.bw, pc.isProxy, wr.req.extra, pc.waitForContinue(wr.continueCh))
2462 if bre, ok := err.(requestBodyReadError); ok {
2463 err = bre.error
2464
2465
2466
2467
2468
2469
2470
2471 wr.req.setError(err)
2472 }
2473 if err == nil {
2474 err = pc.bw.Flush()
2475 }
2476 if err != nil {
2477 if pc.nwrite == startBytesWritten {
2478 err = nothingWrittenError{err}
2479 }
2480 }
2481 pc.writeErrCh <- err
2482 wr.ch <- err
2483 if err != nil {
2484 pc.close(err)
2485 return
2486 }
2487 case <-pc.closech:
2488 return
2489 }
2490 }
2491 }
2492
2493
2494
2495
2496
2497
2498
2499 var maxWriteWaitBeforeConnReuse = 50 * time.Millisecond
2500
2501
2502
2503 func (pc *persistConn) wroteRequest() bool {
2504 select {
2505 case err := <-pc.writeErrCh:
2506
2507
2508 return err == nil
2509 default:
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520 t := time.NewTimer(maxWriteWaitBeforeConnReuse)
2521 defer t.Stop()
2522 select {
2523 case err := <-pc.writeErrCh:
2524 return err == nil
2525 case <-t.C:
2526 return false
2527 }
2528 }
2529 }
2530
2531
2532
2533 type responseAndError struct {
2534 _ incomparable
2535 res *Response
2536 err error
2537 }
2538
2539 type requestAndChan struct {
2540 _ incomparable
2541 req *Request
2542 cancelKey cancelKey
2543 ch chan responseAndError
2544
2545
2546
2547
2548 addedGzip bool
2549
2550
2551
2552
2553
2554 continueCh chan<- struct{}
2555
2556 callerGone <-chan struct{}
2557 }
2558
2559
2560
2561
2562
2563 type writeRequest struct {
2564 req *transportRequest
2565 ch chan<- error
2566
2567
2568
2569
2570 continueCh <-chan struct{}
2571 }
2572
2573 type httpError struct {
2574 err string
2575 timeout bool
2576 }
2577
2578 func (e *httpError) Error() string { return e.err }
2579 func (e *httpError) Timeout() bool { return e.timeout }
2580 func (e *httpError) Temporary() bool { return true }
2581
2582 var errTimeout error = &httpError{err: "net/http: timeout awaiting response headers", timeout: true}
2583
2584
2585
2586 var errRequestCanceled = http2errRequestCanceled
2587 var errRequestCanceledConn = errors.New("net/http: request canceled while waiting for connection")
2588
2589 func nop() {}
2590
2591
2592 var (
2593 testHookEnterRoundTrip = nop
2594 testHookWaitResLoop = nop
2595 testHookRoundTripRetried = nop
2596 testHookPrePendingDial = nop
2597 testHookPostPendingDial = nop
2598
2599 testHookMu sync.Locker = fakeLocker{}
2600 testHookReadLoopBeforeNextRead = nop
2601 )
2602
2603 func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err error) {
2604 testHookEnterRoundTrip()
2605 if !pc.t.replaceReqCanceler(req.cancelKey, pc.cancelRequest) {
2606 pc.t.putOrCloseIdleConn(pc)
2607 return nil, errRequestCanceled
2608 }
2609 pc.mu.Lock()
2610 pc.numExpectedResponses++
2611 headerFn := pc.mutateHeaderFunc
2612 pc.mu.Unlock()
2613
2614 if headerFn != nil {
2615 headerFn(req.extraHeaders())
2616 }
2617
2618
2619
2620
2621
2622 requestedGzip := false
2623 if !pc.t.DisableCompression &&
2624 req.Header.Get("Accept-Encoding") == "" &&
2625 req.Header.Get("Range") == "" &&
2626 req.Method != "HEAD" {
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639 requestedGzip = true
2640 req.extraHeaders().Set("Accept-Encoding", "gzip")
2641 }
2642
2643 var continueCh chan struct{}
2644 if req.ProtoAtLeast(1, 1) && req.Body != nil && req.expectsContinue() {
2645 continueCh = make(chan struct{}, 1)
2646 }
2647
2648 if pc.t.DisableKeepAlives &&
2649 !req.wantsClose() &&
2650 !isProtocolSwitchHeader(req.Header) {
2651 req.extraHeaders().Set("Connection", "close")
2652 }
2653
2654 gone := make(chan struct{})
2655 defer close(gone)
2656
2657 defer func() {
2658 if err != nil {
2659 pc.t.setReqCanceler(req.cancelKey, nil)
2660 }
2661 }()
2662
2663 const debugRoundTrip = false
2664
2665
2666
2667
2668 startBytesWritten := pc.nwrite
2669 writeErrCh := make(chan error, 1)
2670 pc.writech <- writeRequest{req, writeErrCh, continueCh}
2671
2672 resc := make(chan responseAndError)
2673 pc.reqch <- requestAndChan{
2674 req: req.Request,
2675 cancelKey: req.cancelKey,
2676 ch: resc,
2677 addedGzip: requestedGzip,
2678 continueCh: continueCh,
2679 callerGone: gone,
2680 }
2681
2682 var respHeaderTimer <-chan time.Time
2683 cancelChan := req.Request.Cancel
2684 ctxDoneChan := req.Context().Done()
2685 pcClosed := pc.closech
2686 canceled := false
2687 for {
2688 testHookWaitResLoop()
2689 select {
2690 case err := <-writeErrCh:
2691 if debugRoundTrip {
2692 req.logf("writeErrCh resv: %T/%#v", err, err)
2693 }
2694 if err != nil {
2695 pc.close(fmt.Errorf("write error: %w", err))
2696 return nil, pc.mapRoundTripError(req, startBytesWritten, err)
2697 }
2698 if d := pc.t.ResponseHeaderTimeout; d > 0 {
2699 if debugRoundTrip {
2700 req.logf("starting timer for %v", d)
2701 }
2702 timer := time.NewTimer(d)
2703 defer timer.Stop()
2704 respHeaderTimer = timer.C
2705 }
2706 case <-pcClosed:
2707 pcClosed = nil
2708 if canceled || pc.t.replaceReqCanceler(req.cancelKey, nil) {
2709 if debugRoundTrip {
2710 req.logf("closech recv: %T %#v", pc.closed, pc.closed)
2711 }
2712 return nil, pc.mapRoundTripError(req, startBytesWritten, pc.closed)
2713 }
2714 case <-respHeaderTimer:
2715 if debugRoundTrip {
2716 req.logf("timeout waiting for response headers.")
2717 }
2718 pc.close(errTimeout)
2719 return nil, errTimeout
2720 case re := <-resc:
2721 if (re.res == nil) == (re.err == nil) {
2722 panic(fmt.Sprintf("internal error: exactly one of res or err should be set; nil=%v", re.res == nil))
2723 }
2724 if debugRoundTrip {
2725 req.logf("resc recv: %p, %T/%#v", re.res, re.err, re.err)
2726 }
2727 if re.err != nil {
2728 return nil, pc.mapRoundTripError(req, startBytesWritten, re.err)
2729 }
2730 return re.res, nil
2731 case <-cancelChan:
2732 canceled = pc.t.cancelRequest(req.cancelKey, errRequestCanceled)
2733 cancelChan = nil
2734 case <-ctxDoneChan:
2735 canceled = pc.t.cancelRequest(req.cancelKey, req.Context().Err())
2736 cancelChan = nil
2737 ctxDoneChan = nil
2738 }
2739 }
2740 }
2741
2742
2743
2744 type tLogKey struct{}
2745
2746 func (tr *transportRequest) logf(format string, args ...any) {
2747 if logf, ok := tr.Request.Context().Value(tLogKey{}).(func(string, ...any)); ok {
2748 logf(time.Now().Format(time.RFC3339Nano)+": "+format, args...)
2749 }
2750 }
2751
2752
2753
2754 func (pc *persistConn) markReused() {
2755 pc.mu.Lock()
2756 pc.reused = true
2757 pc.mu.Unlock()
2758 }
2759
2760
2761
2762
2763
2764
2765 func (pc *persistConn) close(err error) {
2766 pc.mu.Lock()
2767 defer pc.mu.Unlock()
2768 pc.closeLocked(err)
2769 }
2770
2771 func (pc *persistConn) closeLocked(err error) {
2772 if err == nil {
2773 panic("nil error")
2774 }
2775 pc.broken = true
2776 if pc.closed == nil {
2777 pc.closed = err
2778 pc.t.decConnsPerHost(pc.cacheKey)
2779
2780
2781 if pc.alt == nil {
2782 if err != errCallerOwnsConn {
2783 pc.conn.Close()
2784 }
2785 close(pc.closech)
2786 }
2787 }
2788 pc.mutateHeaderFunc = nil
2789 }
2790
2791 var portMap = map[string]string{
2792 "http": "80",
2793 "https": "443",
2794 "socks5": "1080",
2795 }
2796
2797 func idnaASCIIFromURL(url *url.URL) string {
2798 addr := url.Hostname()
2799 if v, err := idnaASCII(addr); err == nil {
2800 addr = v
2801 }
2802 return addr
2803 }
2804
2805
2806 func canonicalAddr(url *url.URL) string {
2807 port := url.Port()
2808 if port == "" {
2809 port = portMap[url.Scheme]
2810 }
2811 return net.JoinHostPort(idnaASCIIFromURL(url), port)
2812 }
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825 type bodyEOFSignal struct {
2826 body io.ReadCloser
2827 mu sync.Mutex
2828 closed bool
2829 rerr error
2830 fn func(error) error
2831 earlyCloseFn func() error
2832 }
2833
2834 var errReadOnClosedResBody = errors.New("http: read on closed response body")
2835
2836 func (es *bodyEOFSignal) Read(p []byte) (n int, err error) {
2837 es.mu.Lock()
2838 closed, rerr := es.closed, es.rerr
2839 es.mu.Unlock()
2840 if closed {
2841 return 0, errReadOnClosedResBody
2842 }
2843 if rerr != nil {
2844 return 0, rerr
2845 }
2846
2847 n, err = es.body.Read(p)
2848 if err != nil {
2849 es.mu.Lock()
2850 defer es.mu.Unlock()
2851 if es.rerr == nil {
2852 es.rerr = err
2853 }
2854 err = es.condfn(err)
2855 }
2856 return
2857 }
2858
2859 func (es *bodyEOFSignal) Close() error {
2860 es.mu.Lock()
2861 defer es.mu.Unlock()
2862 if es.closed {
2863 return nil
2864 }
2865 es.closed = true
2866 if es.earlyCloseFn != nil && es.rerr != io.EOF {
2867 return es.earlyCloseFn()
2868 }
2869 err := es.body.Close()
2870 return es.condfn(err)
2871 }
2872
2873
2874 func (es *bodyEOFSignal) condfn(err error) error {
2875 if es.fn == nil {
2876 return err
2877 }
2878 err = es.fn(err)
2879 es.fn = nil
2880 return err
2881 }
2882
2883
2884
2885 type gzipReader struct {
2886 _ incomparable
2887 body *bodyEOFSignal
2888 zr *gzip.Reader
2889 zerr error
2890 }
2891
2892 func (gz *gzipReader) Read(p []byte) (n int, err error) {
2893 if gz.zr == nil {
2894 if gz.zerr == nil {
2895 gz.zr, gz.zerr = gzip.NewReader(gz.body)
2896 }
2897 if gz.zerr != nil {
2898 return 0, gz.zerr
2899 }
2900 }
2901
2902 gz.body.mu.Lock()
2903 if gz.body.closed {
2904 err = errReadOnClosedResBody
2905 }
2906 gz.body.mu.Unlock()
2907
2908 if err != nil {
2909 return 0, err
2910 }
2911 return gz.zr.Read(p)
2912 }
2913
2914 func (gz *gzipReader) Close() error {
2915 return gz.body.Close()
2916 }
2917
2918 type tlsHandshakeTimeoutError struct{}
2919
2920 func (tlsHandshakeTimeoutError) Timeout() bool { return true }
2921 func (tlsHandshakeTimeoutError) Temporary() bool { return true }
2922 func (tlsHandshakeTimeoutError) Error() string { return "net/http: TLS handshake timeout" }
2923
2924
2925
2926
2927 type fakeLocker struct{}
2928
2929 func (fakeLocker) Lock() {}
2930 func (fakeLocker) Unlock() {}
2931
2932
2933
2934
2935 func cloneTLSConfig(cfg *tls.Config) *tls.Config {
2936 if cfg == nil {
2937 return &tls.Config{}
2938 }
2939 return cfg.Clone()
2940 }
2941
2942 type connLRU struct {
2943 ll *list.List
2944 m map[*persistConn]*list.Element
2945 }
2946
2947
2948 func (cl *connLRU) add(pc *persistConn) {
2949 if cl.ll == nil {
2950 cl.ll = list.New()
2951 cl.m = make(map[*persistConn]*list.Element)
2952 }
2953 ele := cl.ll.PushFront(pc)
2954 if _, ok := cl.m[pc]; ok {
2955 panic("persistConn was already in LRU")
2956 }
2957 cl.m[pc] = ele
2958 }
2959
2960 func (cl *connLRU) removeOldest() *persistConn {
2961 ele := cl.ll.Back()
2962 pc := ele.Value.(*persistConn)
2963 cl.ll.Remove(ele)
2964 delete(cl.m, pc)
2965 return pc
2966 }
2967
2968
2969 func (cl *connLRU) remove(pc *persistConn) {
2970 if ele, ok := cl.m[pc]; ok {
2971 cl.ll.Remove(ele)
2972 delete(cl.m, pc)
2973 }
2974 }
2975
2976
2977 func (cl *connLRU) len() int {
2978 return len(cl.m)
2979 }
2980
View as plain text