diff --git a/docs/faq.rst b/docs/faq.rst index 03c5ce54..a75e6b0a 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -60,3 +60,51 @@ setting the ``expect`` request option to ``false``: // Disable the expect header on all client requests $client->setConfig('defaults/expect', false) + +How can I add custom cURL options? +================================== + +cURL offer a huge number of `customizable options `_. +While Guzzle normalizes many of these options across different adapters, there +are times when you need to set custom cURL options. This can be accomplished +by passing an associative array of cURL settings in the **curl** key of the +**config** request option. + +For example, let's say you need to customize the outgoing network interface +used with a client. + +.. code-block:: php + + $client->get('/', [ + 'config' => [ + 'curl' => [ + CURLOPT_INTERFACE => 'xxx.xxx.xxx.xxx' + ] + ] + ]); + +How can I add custom stream context options? +============================================ + +You can pass custom `stream context options `_ +using the **stream_context** key of the **config** request option. The +**stream_context** array is an associative array where each key is a PHP +transport, and each value is an associative array of transport options. + +For example, let's say you need to customize the outgoing network interface +used with a client and allow self-signed certificates. + +.. code-block:: php + + $client->get('/', [ + 'config' => [ + 'stream_context' => [ + 'ssl' => [ + 'allow_self_signed' => true + ], + 'socket' => [ + 'bindto' => 'xxx.xxx.xxx.xxx' + ] + ] + ] + ]); diff --git a/src/Adapter/StreamAdapter.php b/src/Adapter/StreamAdapter.php index aa7b0d19..b6c7728c 100644 --- a/src/Adapter/StreamAdapter.php +++ b/src/Adapter/StreamAdapter.php @@ -3,13 +3,19 @@ namespace GuzzleHttp\Adapter; use GuzzleHttp\Event\RequestEvents; +use GuzzleHttp\Exception\AdapterException; use GuzzleHttp\Exception\RequestException; use GuzzleHttp\Message\MessageFactoryInterface; use GuzzleHttp\Message\RequestInterface; use GuzzleHttp\Stream; /** - * HTTP adapter that uses PHP's HTTP stream wrapper + * HTTP adapter that uses PHP's HTTP stream wrapper. + * + * When using the StreamAdapter, custom stream context options can be specified + * using the **stream_context** option in a request's **config** option. The + * structure of the "stream_context" option is an associative array where each + * key is a transport name and each option is an associative array of options. */ class StreamAdapter implements AdapterInterface { @@ -286,4 +292,17 @@ class StreamAdapter implements AdapterInterface fwrite($value, "\n"); }; } + + private function add_stream_context( + RequestInterface $request, + &$options, + $value, + &$params + ) { + if (!is_array($value)) { + throw new AdapterException('stream_context must be an array'); + } + + $options = array_replace_recursive($options, $value); + } } diff --git a/tests/Adapter/StreamAdapterTest.php b/tests/Adapter/StreamAdapterTest.php index 9a61d053..2c8967c6 100644 --- a/tests/Adapter/StreamAdapterTest.php +++ b/tests/Adapter/StreamAdapterTest.php @@ -337,4 +337,43 @@ class StreamAdapterTest extends \PHPUnit_Framework_TestCase $opts = stream_context_get_options($this->getStreamFromBody($body)); $this->assertEquals($url, $opts['http']['proxy']); } + + public function testPerformsShallowMergeOfCustomContextOptions() + { + $body = $this->getSendResult([ + 'stream' => true, + 'config' => [ + 'stream_context' => [ + 'http' => [ + 'request_fulluri' => true, + 'method' => 'HEAD' + ], + 'socket' => [ + 'bindto' => '127.0.0.1:0' + ], + 'ssl' => [ + 'verify_peer' => false + ] + ] + ] + ])->getBody(); + + $opts = stream_context_get_options($this->getStreamFromBody($body)); + $this->assertEquals('HEAD', $opts['http']['method']); + $this->assertTrue($opts['http']['request_fulluri']); + $this->assertFalse($opts['ssl']['verify_peer']); + $this->assertEquals('127.0.0.1:0', $opts['socket']['bindto']); + } + + /** + * @expectedException \GuzzleHttp\Exception\RequestException + * @expectedExceptionMessage stream_context must be an array + */ + public function testEnsuresThatStreamContextIsAnArray() + { + $this->getSendResult([ + 'stream' => true, + 'config' => ['stream_context' => 'foo'] + ]); + } }