Skip to content

Commit

Permalink
Custom option for cURL multi handler
Browse files Browse the repository at this point in the history
  • Loading branch information
alexeyshockov committed Jul 9, 2019
1 parent ca2892a commit 27df4df
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 4 deletions.
17 changes: 17 additions & 0 deletions docs/faq.rst
Expand Up @@ -65,6 +65,23 @@ used with a client.
]
]);
If you use asynchronous requests with cURL multi handler and want to tweak it,
additional options can be specified as an associative array in the
**multi_handle_options** key of the ``CurlMultiHandler`` constructor.

.. code-block:: php
use \GuzzleHttp\Client;
use \GuzzleHttp\HandlerStack;
use \GuzzleHttp\Handler\CurlMultiHandler;
$client = new Client(['handler' => HandlerStack::create(new CurlMultiHandler([
'options' => [
CURLMOPT_MAX_TOTAL_CONNECTIONS => 50,
CURLMOPT_MAX_HOST_CONNECTIONS => 5,
]
]))]);
How can I add custom stream context options?
============================================
Expand Down
18 changes: 16 additions & 2 deletions src/Handler/CurlMultiHandler.php
@@ -1,9 +1,9 @@
<?php
namespace GuzzleHttp\Handler;

use GuzzleHttp\Exception\InvalidArgumentException;
use GuzzleHttp\Promise as P;
use GuzzleHttp\Promise\Promise;
use GuzzleHttp\Psr7;
use Psr\Http\Message\RequestInterface;

/**
Expand All @@ -23,13 +23,16 @@ class CurlMultiHandler
private $active;
private $handles = [];
private $delays = [];
private $options = [];

/**
* This handler accepts the following options:
*
* - handle_factory: An optional factory used to create curl handles
* - select_timeout: Optional timeout (in seconds) to block before timing
* out while selecting curl handles. Defaults to 1 second.
* - options: An associative array of CURLMOPT_* options and
* corresponding values for curl_multi_setopt()
*
* @param array $options
*/
Expand All @@ -45,12 +48,23 @@ public function __construct(array $options = [])
} else {
$this->selectTimeout = 1;
}

$this->options = isset($options['options']) ? $options['options'] : [];
}

public function __get($name)
{
if ($name === '_mh') {
return $this->_mh = curl_multi_init();
$this->_mh = curl_multi_init();

foreach ($this->options as $option => $value) {
// A warning is raised in case of a wrong option.
curl_multi_setopt($this->_mh, $option, $value);
}

// Further calls to _mh will return the value directly, without entering the
// __get() method at all.
return $this->_mh;
}

throw new \BadMethodCallException();
Expand Down
25 changes: 25 additions & 0 deletions tests/Handler/CurlMultiHandlerTest.php
Expand Up @@ -9,6 +9,31 @@

class CurlMultiHandlerTest extends TestCase
{
public function setUp()
{
$_SERVER['curl_test'] = true;
unset($_SERVER['_curl_multi']);
}

public function tearDown()
{
unset($_SERVER['_curl_multi'], $_SERVER['curl_test']);
}

public function testCanAddCustomCurlOptions()
{
Server::flush();
Server::enqueue([new Response()]);
$a = new CurlMultiHandler(['options' => [
CURLMOPT_PIPELINING => 1,
CURLMOPT_MAXCONNECTS => 5,
]]);
$request = new Request('GET', Server::$url);
$a($request, []);
$this->assertEquals(1, $_SERVER['_curl_multi'][CURLMOPT_PIPELINING]);
$this->assertEquals(5, $_SERVER['_curl_multi'][CURLMOPT_MAXCONNECTS]);
}

public function testSendsRequest()
{
Server::enqueue([new Response()]);
Expand Down
14 changes: 12 additions & 2 deletions tests/bootstrap.php
Expand Up @@ -10,7 +10,7 @@
});
}

// Override curl_setopt_array() to get the last set curl options
// Override curl_setopt_array() and curl_multi_setopt() to get the last set curl options
namespace GuzzleHttp\Handler {
function curl_setopt_array($handle, array $options)
{
Expand All @@ -19,6 +19,16 @@ function curl_setopt_array($handle, array $options)
} else {
unset($_SERVER['_curl']);
}
\curl_setopt_array($handle, $options);
return \curl_setopt_array($handle, $options);
}

function curl_multi_setopt($handle, $option, $value)
{
if (!empty($_SERVER['curl_test'])) {
$_SERVER['_curl_multi'][$option] = $value;
} else {
unset($_SERVER['_curl_multi']);
}
return \curl_multi_setopt($handle, $option, $value);
}
}

0 comments on commit 27df4df

Please sign in to comment.