Chart

Transport

transport.svg

Client

client.svg

Code

Transport

  1. type Transport struct {
  2. idleMu sync.Mutex
  3. closeIdle bool // user has requested to close all idle conns
  4. idleConn map[connectMethodKey][]*persistConn // most recently used at end
  5. idleConnWait map[connectMethodKey]wantConnQueue // waiting getConns
  6. idleLRU connLRU
  7. reqMu sync.Mutex
  8. reqCanceler map[*Request]func(error)
  9. altMu sync.Mutex // guards changing altProto only
  10. altProto atomic.Value // of nil or map[string]RoundTripper, key is URI scheme
  11. connsPerHostMu sync.Mutex
  12. connsPerHost map[connectMethodKey]int
  13. connsPerHostWait map[connectMethodKey]wantConnQueue // waiting getConns
  14. ...
  15. }

wantConnQueue

  1. // A wantConnQueue is a queue of wantConns.
  2. type wantConnQueue struct {
  3. // This is a queue, not a deque.
  4. // It is split into two stages - head[headPos:] and tail.
  5. // popFront is trivial (headPos++) on the first stage, and
  6. // pushBack is trivial (append) on the second stage.
  7. // If the first stage is empty, popFront can swap the
  8. // first and second stages to remedy the situation.
  9. //
  10. // This two-stage split is analogous to the use of two lists
  11. // in Okasaki's purely functional queue but without the
  12. // overhead of reversing the list when swapping stages.
  13. head []*wantConn
  14. headPos int
  15. tail []*wantConn
  16. }

wantConn

  1. // A wantConn records state about a wanted connection
  2. // (that is, an active call to getConn).
  3. // The conn may be gotten by dialing or by finding an idle connection,
  4. // or a cancellation may make the conn no longer wanted.
  5. // These three options are racing against each other and use
  6. // wantConn to coordinate and agree about the winning outcome.
  7. type wantConn struct {
  8. cm connectMethod
  9. key connectMethodKey // cm.key()
  10. ctx context.Context // context for dial
  11. ready chan struct{} // closed when pc, err pair is delivered
  12. // hooks for testing to know when dials are done
  13. // beforeDial is called in the getConn goroutine when the dial is queued.
  14. // afterDial is called when the dial is completed or cancelled.
  15. beforeDial func()
  16. afterDial func()
  17. mu sync.Mutex // protects pc, err, close(ready)
  18. pc *persistConn
  19. err error
  20. }

persistConn

  1. persistConn struct {
  2. // alt optionally specifies the TLS NextProto RoundTripper.
  3. // This is used for HTTP/2 today and future protocols later.
  4. // If it's non-nil, the rest of the fields are unused.
  5. alt RoundTripper
  6. t *Transport
  7. cacheKey connectMethodKey
  8. conn net.Conn
  9. tlsState *tls.ConnectionState
  10. br *bufio.Reader // from conn
  11. bw *bufio.Writer // to conn
  12. nwrite int64 // bytes written
  13. reqch chan requestAndChan // written by roundTrip; read by readLoop
  14. writech chan writeRequest // written by roundTrip; read by writeLoop
  15. closech chan struct{} // closed when conn closed
  16. isProxy bool
  17. sawEOF bool // whether we've seen EOF from conn; owned by readLoop
  18. readLimit int64 // bytes allowed to be read; owned by readLoop
  19. // writeErrCh passes the request write error (usually nil)
  20. // from the writeLoop goroutine to the readLoop which passes
  21. // it off to the res.Body reader, which then uses it to decide
  22. // whether or not a connection can be reused. Issue 7569.
  23. writeErrCh chan error
  24. writeLoopDone chan struct{} // closed when write loop ends
  25. // Both guarded by Transport.idleMu:
  26. idleAt time.Time // time it last become idle
  27. idleTimer *time.Timer // holding an AfterFunc to close it
  28. mu sync.Mutex // guards following fields
  29. numExpectedResponses int
  30. closed error // set non-nil when conn is closed, before closech is closed
  31. canceledErr error // set non-nil if conn is canceled
  32. broken bool // an error has happened on this connection; marked broken so it's not reused.
  33. reused bool // whether conn has had successful request/response and is being reused.
  34. // mutateHeaderFunc is an optional func to modify extra
  35. // headers on each outbound request before it's written. (the
  36. // original Request given to RoundTrip is not modified)
  37. mutateHeaderFunc func(Header)
  38. }

Client

  1. type RoundTripper interface {
  2. RoundTrip(*Request) (*Response, error)
  3. }
  4. type Client struct {
  5. Transport RoundTripper
  6. CheckRedirect func(req *Request, via []*Request) error
  7. Jar CookieJar
  8. Timeout time.Duration
  9. }
  10. var DefaultTransport RoundTripper = &Transport{
  11. Proxy: ProxyFromEnvironment,
  12. DialContext: (&net.Dialer{
  13. Timeout: 30 * time.Second,
  14. KeepAlive: 30 * time.Second,
  15. DualStack: true,
  16. }).DialContext,
  17. ForceAttemptHTTP2: true,
  18. MaxIdleConns: 100,
  19. IdleConnTimeout: 90 * time.Second,
  20. TLSHandshakeTimeout: 10 * time.Second,
  21. ExpectContinueTimeout: 1 * time.Second,
  22. }