1=============== 2Client Handlers 3=============== 4 5Client handlers accept a request array and return a future response array that 6can be used synchronously as an array or asynchronously using a promise. 7 8Built-In Handlers 9----------------- 10 11RingPHP comes with three built-in client handlers. 12 13Stream Handler 14~~~~~~~~~~~~~~ 15 16The ``GuzzleHttp\Ring\Client\StreamHandler`` uses PHP's 17`http stream wrapper <http://php.net/manual/en/wrappers.http.php>`_ to send 18requests. 19 20.. note:: 21 22 This handler cannot send requests concurrently. 23 24You can provide an associative array of custom stream context options to the 25StreamHandler using the ``stream_context`` key of the ``client`` request 26option. 27 28.. code-block:: php 29 30 use GuzzleHttp\Ring\Client\StreamHandler; 31 32 $response = $handler([ 33 'http_method' => 'GET', 34 'uri' => '/', 35 'headers' => ['host' => ['httpbin.org']], 36 'client' => [ 37 'stream_context' => [ 38 'http' => [ 39 'request_fulluri' => true, 40 'method' => 'HEAD' 41 ], 42 'socket' => [ 43 'bindto' => '127.0.0.1:0' 44 ], 45 'ssl' => [ 46 'verify_peer' => false 47 ] 48 ] 49 ] 50 ]); 51 52 // Even though it's already completed, you can still use a promise 53 $response->then(function ($response) { 54 echo $response['status']; // 200 55 }); 56 57 // Or access the response using the future interface 58 echo $response['status']; // 200 59 60cURL Handler 61~~~~~~~~~~~~ 62 63The ``GuzzleHttp\Ring\Client\CurlHandler`` can be used with PHP 5.5+ to send 64requests using cURL easy handles. This handler is great for sending requests 65one at a time because the execute and select loop is implemented in C code 66which executes faster and consumes less memory than using PHP's 67``curl_multi_*`` interface. 68 69.. note:: 70 71 This handler cannot send requests concurrently. 72 73When using the CurlHandler, custom curl options can be specified as an 74associative array of `cURL option constants <http://php.net/manual/en/curl.constants.php>`_ 75mapping to values in the ``client`` option of a requst using the **curl** key. 76 77.. code-block:: php 78 79 use GuzzleHttp\Ring\Client\CurlHandler; 80 81 $handler = new CurlHandler(); 82 83 $request = [ 84 'http_method' => 'GET', 85 'headers' => ['host' => [Server::$host]], 86 'client' => ['curl' => [CURLOPT_LOW_SPEED_LIMIT => 10]] 87 ]; 88 89 $response = $handler($request); 90 91 // The response can be used directly as an array. 92 echo $response['status']; // 200 93 94 // Or, it can be used as a promise (that has already fulfilled). 95 $response->then(function ($response) { 96 echo $response['status']; // 200 97 }); 98 99cURL Multi Handler 100~~~~~~~~~~~~~~~~~~ 101 102The ``GuzzleHttp\Ring\Client\CurlMultiHandler`` transfers requests using 103cURL's `multi API <http://curl.haxx.se/libcurl/c/libcurl-multi.html>`_. The 104``CurlMultiHandler`` is great for sending requests concurrently. 105 106.. code-block:: php 107 108 use GuzzleHttp\Ring\Client\CurlMultiHandler; 109 110 $handler = new CurlMultiHandler(); 111 112 $request = [ 113 'http_method' => 'GET', 114 'headers' => ['host' => [Server::$host]] 115 ]; 116 117 // this call returns a future array immediately. 118 $response = $handler($request); 119 120 // Ideally, you should use the promise API to not block. 121 $response 122 ->then(function ($response) { 123 // Got the response at some point in the future 124 echo $response['status']; // 200 125 // Don't break the chain 126 return $response; 127 })->then(function ($response) { 128 // ... 129 }); 130 131 // If you really need to block, then you can use the response as an 132 // associative array. This will block until it has completed. 133 echo $response['status']; // 200 134 135Just like the ``CurlHandler``, the ``CurlMultiHandler`` accepts custom curl 136option in the ``curl`` key of the ``client`` request option. 137 138Mock Handler 139~~~~~~~~~~~~ 140 141The ``GuzzleHttp\Ring\Client\MockHandler`` is used to return mock responses. 142When constructed, the handler can be configured to return the same response 143array over and over, a future response, or a the evaluation of a callback 144function. 145 146.. code-block:: php 147 148 use GuzzleHttp\Ring\Client\MockHandler; 149 150 // Return a canned response. 151 $mock = new MockHandler(['status' => 200]); 152 $response = $mock([]); 153 assert(200 == $response['status']); 154 assert([] == $response['headers']); 155 156Implementing Handlers 157--------------------- 158 159Client handlers are just PHP callables (functions or classes that have the 160``__invoke`` magic method). The callable accepts a request array and MUST 161return an instance of ``GuzzleHttp\Ring\Future\FutureArrayInterface`` so that 162the response can be used by both blocking and non-blocking consumers. 163 164Handlers need to follow a few simple rules: 165 1661. Do not throw exceptions. If an error is encountered, return an array that 167 contains the ``error`` key that maps to an ``\Exception`` value. 1682. If the request has a ``delay`` client option, then the handler should only 169 send the request after the specified delay time in seconds. Blocking 170 handlers may find it convenient to just let the 171 ``GuzzleHttp\Ring\Core::doSleep($request)`` function handle this for them. 1723. Always return an instance of ``GuzzleHttp\Ring\Future\FutureArrayInterface``. 1734. Complete any outstanding requests when the handler is destructed. 174