Skip to content

Commit

Permalink
Merge pull request #764 from stripe/ob-callback-retries
Browse files Browse the repository at this point in the history
Add support for HTTP request monitoring callback
  • Loading branch information
ob-stripe authored Oct 16, 2019
2 parents 8278b83 + 5fc6d0c commit b078bfd
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 1 deletion.
41 changes: 40 additions & 1 deletion lib/HttpClient/CurlClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ public static function instance()

protected $curlHandle = null;

protected $requestStatusCallback = null;

/**
* CurlClient constructor.
*
Expand Down Expand Up @@ -124,6 +126,33 @@ public function setEnableHttp2($enable)
$this->enableHttp2 = $enable;
}

/**
* @return callable|null
*/
public function getRequestStatusCallback()
{
return $this->requestStatusCallback;
}

/**
* Sets a callback that is called after each request. The callback will
* receive the following parameters:
*
* 1. string $rbody The response body
* 2. integer $rcode The response status code
* 3. \Stripe\Util\CaseInsensitiveArray $rheaders The response headers
* 4. integer $errno The curl error number
* 5. string|null $message The curl error message
* 6. boolean $shouldRetry Whether the request will be retried
* 7. integer $numRetries The number of the retry attempt
*
* @param callable|null $requestStatusCallback
*/
public function setRequestStatusCallback($requestStatusCallback)
{
$this->requestStatusCallback = $requestStatusCallback;
}

// USER DEFINED TIMEOUTS

const DEFAULT_TIMEOUT = 80;
Expand Down Expand Up @@ -250,6 +279,7 @@ private function executeRequestWithRetries($opts, $absUrl)
while (true) {
$rcode = 0;
$errno = 0;
$message = null;

// Create a callback to capture HTTP headers for the response
$rheaders = new Util\CaseInsensitiveArray();
Expand Down Expand Up @@ -278,7 +308,16 @@ private function executeRequestWithRetries($opts, $absUrl)
$this->closeCurlHandle();
}

if ($this->shouldRetry($errno, $rcode, $rheaders, $numRetries)) {
$shouldRetry = $this->shouldRetry($errno, $rcode, $rheaders, $numRetries);

if (is_callable($this->getRequestStatusCallback())) {
call_user_func_array(
$this->getRequestStatusCallback(),
[$rbody, $rcode, $rheaders, $errno, $message, $shouldRetry, $numRetries]
);
}

if ($shouldRetry) {
$numRetries += 1;
$sleepSeconds = $this->sleepTime($numRetries, $rheaders);
usleep(intval($sleepSeconds * 1000000));
Expand Down
28 changes: 28 additions & 0 deletions tests/Stripe/HttpClient/CurlClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -297,4 +297,32 @@ public function testResponseHeadersCaseInsensitive()
$this->assertNotNull($headers['request-id']);
$this->assertEquals($headers['request-id'], $headers['Request-Id']);
}

public function testSetRequestStatusCallback()
{
try {
$called = false;

$curl = new CurlClient();
$curl->setRequestStatusCallback(function ($rbody, $rcode, $rheaders, $errno, $message, $willBeRetried, $numRetries) use (&$called) {
$called = true;

$this->assertTrue(is_string($rbody));
$this->assertEquals(200, $rcode);
$this->assertEquals('req_123', $rheaders['request-id']);
$this->assertEquals(0, $errno);
$this->assertNull($message);
$this->assertFalse($willBeRetried);
$this->assertEquals(0, $numRetries);
});

\Stripe\ApiRequestor::setHttpClient($curl);

Charge::all();

$this->assertTrue($called);
} finally {
\Stripe\ApiRequestor::setHttpClient(null);
}
}
}

0 comments on commit b078bfd

Please sign in to comment.