public function sendRequest(\GuzzleHttp\Psr7\Request $request, array $opts=[])
  {
    # Set params
    $retriesLeft = $this->retries;
    $this->lastErrorStr = '';

    # Retry loop
    while ( $retriesLeft>0 )
    {
      # Decrease retry count
      $retriesLeft--;

      $this->timeStart = 0;
      $this->timeHeaders = 0;
      $this->timeResponse = 0;

      try {
        # Make sure we have a GuzzleHttp\Client
        $this->createClient($this->opts);
        $this->timeStart = microtime(true);

        # Request Options
        $opts = array_merge(
          [
            'http_errors' => true,                               // Exceptions on 4xx response codes
            'connect_timeout' => $this->getTimeoutConnect(),     // Connect Timeout (seconds)
            'timeout'  => $this->getTimeoutReceive(),            // Receive Timeout (seconds)
            'verify' => false                                    // Disable SSL verification (handle self generated SSL certs)
          ]
          ,$this->getRequestOptions()
        );

        $sendOpts = array_merge([
           'on_headers' => function (\GuzzleHttp\Psr7\Response $response) {
             $this->timeHeaders = microtime(true)-$this->timeStart;
           },
           'synchronous'      => true,
           'cookies'          => $this->cookieJar,
           'debug'            => false
           // 'on_headers' => function ( \Psr\Http\Message\ResponseInterface $response ) {
           //   error_log( print_r($response->getHeaders(), true) );
           // },
           // 'on_stats' => function ( \GuzzleHttp\TransferStats $status ) {
           //   error_log( $status->getTransferTime().' - '.print_r($status->getHandlerStats(),true) );
           // }
         ],$opts
        );

        # Send the Request
        $this->httpResponse = $this->guzzleClient->send($request, $sendOpts);

        # Successful response, break the loop
        $retriesLeft = 0;

      } catch (\GuzzleHttp\Exception\ConnectException  $e) {
        # Network errors
        #
        # Note: For "Host not found", "DNS failure", "Network errors" etc.
        #       we might not have a Response Object!

        # Set error String
        $this->lastErrorStr = $e->getMessage();

        # Get the Response Object from the Exception
        if ( $e->hasResponse() ) {
          $this->httpResponse = $e->getResponse();
        }

        # No point in retrying
        $retriesLeft = 0;

      } catch (\GuzzleHttp\Exception\BadResponseException $e) {
        # 4xx (ClientException)
        # 5xx (ServerException)
        #
        # Note:  We have a response object available, meaning the target service responded
        #        so no retry needed (and it exists so no SDR reporting)

        # Set error String
        $this->lastErrorStr = $e->getMessage();

        # Get the Response Object from the Exception
        if ( $e->hasResponse() ) {
          $this->httpResponse = $e->getResponse();
        }

        # Break the while loop (no retries for this error)
        $retriesLeft = 0;

      } catch (\GuzzleHttp\Exception\RequestException $e) {
        # Also Catches
        #   TooManyRedirectsException

        # Set error String
        $this->lastErrorStr = $e->getMessage();

        # Get the Response Object from the Exception
        if ( $e->hasResponse() ) {
          $this->httpResponse = $e->getResponse();
        }

        # Should we do a retry?
        if ($retriesLeft>0) {
          $_sec = 0.1; // 0.1 seconds = 100 ms
          usleep($_sec * 1000000);
          unset($_sec);
        }

      } catch (\Exception $e) {
        # General exception
        #

        # Set error String
        $this->lastErrorStr = $e->getMessage();

        # Break the while loop (no retries for this error)
        $retriesLeft = 0;

      } finally {
        $this->timeResponse = microtime(true) - $this->timeStart;

      }

    } // while

    return $this->httpResponse;
  }