Merge "Move several unit tests to directly subclass PHPUnit_Framework_TestCase"
[lhc/web/wiklou.git] / includes / libs / MultiHttpClient.php
index 8ed9ee4..16e0d4f 100644 (file)
@@ -34,6 +34,7 @@
  *                array bodies are encoded as multipart/form-data and strings
  *                use application/x-www-form-urlencoded (headers sent automatically)
  *   - stream   : resource to stream the HTTP response body to
+ *   - proxy    : HTTP proxy to use
  * Request maps can use integer index 0 instead of 'method' and 1 instead of 'url'.
  *
  * @author Aaron Schulz
@@ -52,13 +53,17 @@ class MultiHttpClient {
        protected $usePipelining = false;
        /** @var integer */
        protected $maxConnsPerHost = 50;
+       /** @var string|null proxy */
+       protected $proxy;
 
        /**
         * @param array $options
-        *   - connTimeout     : default connection timeout
-        *   - reqTimeout      : default request timeout
+        *   - connTimeout     : default connection timeout (seconds)
+        *   - reqTimeout      : default request timeout (seconds)
+        *   - proxy           : HTTP proxy to use
         *   - usePipelining   : whether to use HTTP pipelining if possible (for all hosts)
         *   - maxConnsPerHost : maximum number of concurrent connections (per host)
+        * @throws Exception
         */
        public function __construct( array $options ) {
                if ( isset( $options['caBundlePath'] ) ) {
@@ -67,7 +72,7 @@ class MultiHttpClient {
                                throw new Exception( "Cannot find CA bundle: " . $this->caBundlePath );
                        }
                }
-               static $opts = array( 'connTimeout', 'reqTimeout', 'usePipelining', 'maxConnsPerHost' );
+               static $opts = array( 'connTimeout', 'reqTimeout', 'usePipelining', 'maxConnsPerHost', 'proxy' );
                foreach ( $opts as $key ) {
                        if ( isset( $options[$key] ) ) {
                                $this->$key = $options[$key];
@@ -85,13 +90,13 @@ class MultiHttpClient {
         *   - body    : HTTP response body or resource (if "stream" was set)
         *   - error     : Any cURL error string
         * The map also stores integer-indexed copies of these values. This lets callers do:
-        *      <code>
+        * @code
         *              list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $http->run( $req );
-        *  </code>
+        * @endcode
         * @param array $req HTTP request array
         * @param array $opts
-        *   - connTimeout    : connection timeout per request
-        *   - reqTimeout     : post-connection timeout per request
+        *   - connTimeout    : connection timeout per request (seconds)
+        *   - reqTimeout     : post-connection timeout per request (seconds)
         * @return array Response array for request
         */
        final public function run( array $req, array $opts = array() ) {
@@ -103,26 +108,27 @@ class MultiHttpClient {
         * Execute a set of HTTP(S) requests concurrently
         *
         * The maps are returned by this method with the 'response' field set to a map of:
-        *   - code    : HTTP response code or 0 if there was a serious cURL error
-        *   - reason  : HTTP response reason (empty if there was a serious cURL error)
-        *   - headers : <header name/value associative array>
-        *   - body    : HTTP response body or resource (if "stream" was set)
+        *   - code    : HTTP response code or 0 if there was a serious cURL error
+        *   - reason  : HTTP response reason (empty if there was a serious cURL error)
+        *   - headers : <header name/value associative array>
+        *   - body    : HTTP response body or resource (if "stream" was set)
         *   - error   : Any cURL error string
-        * The map also stores integer-indexed copies of these values. This lets callers do:
-        *      <code>
-        *              list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $req['response'];
-        *  </code>
+        * The map also stores integer-indexed copies of these values. This lets callers do:
+        * @code
+        *        list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $req['response'];
+        * @endcode
         * All headers in the 'headers' field are normalized to use lower case names.
         * This is true for the request headers and the response headers. Integer-indexed
         * method/URL entries will also be changed to use the corresponding string keys.
         *
         * @param array $reqs Map of HTTP request arrays
         * @param array $opts
-        *   - connTimeout     : connection timeout per request
-        *   - reqTimeout      : post-connection timeout per request
+        *   - connTimeout     : connection timeout per request (seconds)
+        *   - reqTimeout      : post-connection timeout per request (seconds)
         *   - usePipelining   : whether to use HTTP pipelining if possible
         *   - maxConnsPerHost : maximum number of concurrent connections (per host)
         * @return array $reqs With response array populated for each
+        * @throws Exception
         */
        public function runMulti( array $reqs, array $opts = array() ) {
                $chm = $this->getCurlMulti();
@@ -244,12 +250,14 @@ class MultiHttpClient {
         *   - connTimeout    : default connection timeout
         *   - reqTimeout     : default request timeout
         * @return resource
+        * @throws Exception
         */
        protected function getCurlHandle( array &$req, array $opts = array() ) {
                $ch = curl_init();
 
                curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT,
                        isset( $opts['connTimeout'] ) ? $opts['connTimeout'] : $this->connTimeout );
+               curl_setopt( $ch, CURLOPT_PROXY, isset( $req['proxy'] ) ? $req['proxy'] : $this->proxy );
                curl_setopt( $ch, CURLOPT_TIMEOUT,
                        isset( $opts['reqTimeout'] ) ? $opts['reqTimeout'] : $this->reqTimeout );
                curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, 1 );