code: func (c *HostClient) Do(req *Request, resp *Response) error {
  	var err error
  	var retry bool
  	maxAttempts := c.MaxIdemponentCallAttempts
  	if maxAttempts <= 0 {
  		maxAttempts = DefaultMaxIdemponentCallAttempts
  	}
  	attempts := 0
  
  	atomic.AddInt32(&c.pendingRequests, 1)
  	for {
  		retry, err = c.do(req, resp)
  		if err == nil || !retry {
  			break
  		}
  
  		if !isIdempotent(req) {
  			// Retry non-idempotent requests if the server closes
  			// the connection before sending the response.
  			//
  			// This case is possible if the server closes the idle
  			// keep-alive connection on timeout.
  			//
  			// Apache and nginx usually do this.
  			if err != io.EOF {
  				break
  			}
  		}
  		attempts++
  		if attempts >= maxAttempts {
  			break
  		}
  	}
  	atomic.AddInt32(&c.pendingRequests, -1)
  
  	if err == io.EOF {
  		err = ErrConnectionClosed
  	}
  	return err
  }
docs: // Do performs the given http request and sets the corresponding response.
  //
  // Request must contain at least non-zero RequestURI with full url (including
  // scheme and host) or non-zero Host header + RequestURI.
  //
  // The function doesn't follow redirects. Use Get* for following redirects.
  //
  // Response is ignored if resp is nil.
  //
  // ErrNoFreeConns is returned if all HostClient.MaxConns connections
  // to the host are busy.
  //
  // It is recommended obtaining req and resp via AcquireRequest
  // and AcquireResponse in performance-critical code.