change names of options used for http/2; add https and http/2 tests to benchmark.php 4.7.2
authorgggeek <giunta.gaetano@gmail.com>
Thu, 26 May 2022 22:09:28 +0000 (22:09 +0000)
committergggeek <giunta.gaetano@gmail.com>
Thu, 26 May 2022 22:09:28 +0000 (22:09 +0000)
NEWS
extras/benchmark.php
src/Client.php
tests/6HTTPTest.php

diff --git a/NEWS b/NEWS
index 89026ee..aabea24 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,17 +1,24 @@
+XML-RPC for PHP version 4.7.2 - 2022/5/25
+
+* modified the strings used to tell the client to use http/2: to avoid users mistaking 'http2' for the preferred value,
+  we switched to using `h2` and `h2c`
+
+* improved: the `benchmark.php` file does now also test calls using https and http/2 protocols
+
+
 XML-RPC for PHP version 4.7.1 - 2022/5/25
 
-* fixed: http/2 on non-https requests works in either "prior-knowledge" mode or "upgrade" mode, known as h2c.
-  Given the fact that h2c is not compatible with POST requests, we switched to using "prior-knowledge" mode for requests
-  sent with the `http2` argument passed to the client's constructor or `send` method.
-  NB: this means that requests sent with `http2` are only compatible with servers and proxies known to be http/2 compliant.
+* fixed: http/2 on non-https requests (known as h2c) works in either "prior-knowledge" mode or "upgrade" mode.
+  Given the fact that "upgrade" mode is not compatible with POST requests, we switched to using "prior-knowledge" mode
+  for requests sent with the `h2c` argument passed to the client's constructor or `send` method.
+  NB: this means that requests sent with `h2c` are only compatible with servers and proxies known to be http/2 compliant.
 
 
 XML-RPC for PHP version 4.7.0 - 2022/5/25
 
-
 * new: HTTP/2 is supported by both the Client and Server components (with the php cURL extension being required to use
   it client-side).
-  To force the client to use http/2 and http/2-tls requests, pass `http2` or `http2tls` as 3rd argument to `Client::send`.
+  To force the client to use http/2 over tls or http/2 over tcp requests, pass `h2` or `h2c` as 3rd argument to `Client::send`.
 
 
 XML-RPC for PHP version 4.6.1 - 2022/2/15
index 2f0f55a..baeb23b 100644 (file)
@@ -9,7 +9,6 @@
  * @todo add a check for response ok in call testing
  * @todo add support for --help option to give users the list of supported parameters
  * @todo make number of test iterations flexible
- * @todo add https tests
  **/
 
 use PhpXmlRpc\PhpXmlRpc;
@@ -89,6 +88,7 @@ if ($is_web) {
     }
 }
 
+/*
 // test 'manual style' data encoding vs. 'automatic style' encoding
 begin_test('Data encoding (large array)', 'manual encoding');
 for ($i = 0; $i < $num_tests; $i++) {
@@ -199,11 +199,14 @@ if (function_exists('xmlrpc_decode')) {
     end_test('Data decoding (large array)', 'xmlrpc-epi decoding', $value);
 }
 
+*/
+
 if (!$xd) {
 
     $num_tests = 25;
 
-    /// test multicall vs. many calls vs. keep-alives
+    /// test multicall vs. many calls vs. keep-alives - HTTP
+
     $encoder = new Encoder();
     $value = $encoder->encode($data1, array('auto_dates'));
     $req = new Request('interopEchoTests.echoValue', array($value));
@@ -211,23 +214,22 @@ if (!$xd) {
     for ($i = 0; $i < $num_tests; $i++) {
         $reqs[] = $req;
     }
+
     $server = explode(':', $args['HTTPSERVER']);
     if (count($server) > 1) {
-        $srv = $server[1] . '://' . $server[0] . $args['HTTPURI'];
+        $srv = 'http://' . $server[0] . '://' . $server[1] . $args['HTTPURI'];
         $c = new Client($args['HTTPURI'], $server[0], $server[1]);
     } else {
-        $srv = $args['HTTPSERVER'] . $args['HTTPURI'];
+        $srv = 'http://' . $args['HTTPSERVER'] . $args['HTTPURI'];
         $c = new Client($args['HTTPURI'], $args['HTTPSERVER']);
     }
+
     // do not interfere with http compression
-    $c->accepted_compression = array();
-    //$c->debug=true;
+    $c->setAcceptedCompression(false);
+    //$c->debug = 1;
 
     $testName = "Repeated send (small array) to $srv";
 
-    if (function_exists('gzinflate')) {
-        $c->accepted_compression = null;
-    }
     begin_test($testName, 'http 10');
     $response = array();
     for ($i = 0; $i < $num_tests; $i++) {
@@ -237,24 +239,26 @@ if (!$xd) {
     end_test($testName, 'http 10', $response);
 
     if (function_exists('curl_init')) {
-        begin_test($testName, 'http 11 w. keep-alive');
+        $c->keepalive = false;
+        begin_test($testName, 'http 11 no keepalive');
         $response = array();
         for ($i = 0; $i < $num_tests; $i++) {
             $resp = $c->send($req, 10, 'http11');
             $response[] = $resp->value();
         }
-        end_test($testName, 'http 11 w. keep-alive', $response);
+        end_test($testName, 'http 11 no keepalive', $response);
 
-        $c->keepalive = false;
-        begin_test($testName, 'http 11');
+        begin_test($testName, 'http 11 w. keep-alive');
         $response = array();
         for ($i = 0; $i < $num_tests; $i++) {
             $resp = $c->send($req, 10, 'http11');
             $response[] = $resp->value();
         }
-        end_test($testName, 'http 11', $response);
+        end_test($testName, 'http 11 w. keep-alive', $response);
+        $c->xmlrpc_curl_handle = null;
     }
 
+    // this is a single http call - keepalive on/off does not bother us
     begin_test($testName, 'multicall');
     $response = $c->send($reqs);
     foreach ($response as $key => & $val) {
@@ -275,22 +279,24 @@ if (!$xd) {
         end_test($testName, 'http 10 w. compression', $response);
 
         if (function_exists('curl_init')) {
-            begin_test($testName, 'http 11 w. keep-alive and compression');
+            $c->keepalive = false;
+            begin_test($testName, 'http 11 w. compression and no keepalive');
             $response = array();
             for ($i = 0; $i < $num_tests; $i++) {
                 $resp = $c->send($req, 10, 'http11');
                 $response[] = $resp->value();
             }
-            end_test($testName, 'http 11 w. keep-alive and compression', $response);
+            end_test($testName, 'http 11 w. compression and no keepalive', $response);
 
-            $c->keepalive = false;
-            begin_test($testName, 'http 11 w. compression');
+            $c->keepalive = true;
+            begin_test($testName, 'http 11 w. keep-alive and compression');
             $response = array();
             for ($i = 0; $i < $num_tests; $i++) {
                 $resp = $c->send($req, 10, 'http11');
                 $response[] = $resp->value();
             }
-            end_test($testName, 'http 11 w. compression', $response);
+            end_test($testName, 'http 11 w. keep-alive and compression', $response);
+            $c->xmlrpc_curl_handle = null;
         }
 
         begin_test($testName, 'multicall w. compression');
@@ -300,6 +306,162 @@ if (!$xd) {
         }
         end_test($testName, 'multicall w. compression', $response);
     }
+
+    if (function_exists('curl_init')) {
+
+        /// test multicall vs. many calls vs. keep-alives - HTTPS
+
+        $server = explode(':', $args['HTTPSSERVER']);
+        if (count($server) > 1) {
+            $srv = 'https://' . $server[0] . ':' . $server[1] . $args['HTTPSURI'];
+            $c = new Client($args['HTTPSURI'], $server[0], $server[1], 'https');
+        } else {
+            $srv = 'https://' . $args['HTTPSSERVER'] . $args['HTTPSURI'];
+            $c = new Client($args['HTTPSURI'], $args['HTTPSSERVER'], 443, 'https');
+        }
+        $c->setSSLVerifyPeer(!$args['HTTPSIGNOREPEER']);
+        $c->setSSLVerifyHost($args['HTTPSVERIFYHOST']);
+        // do not interfere with http compression
+        $c->setAcceptedCompression(false);
+        //$c->debug = 1;
+
+        $testName = "Repeated send (small array) to $srv";
+
+        begin_test($testName, 'https no keep-alive');
+        $c->keepalive = false;
+        $response = array();
+        for ($i = 0; $i < $num_tests; $i++) {
+            $resp = $c->send($req);
+            $response[] = $resp->value();
+        }
+        end_test($testName, 'https no keep-alive', $response);
+
+        begin_test($testName, 'https w. keep-alive');
+        $c->keepalive = true;
+        $response = array();
+        for ($i = 0; $i < $num_tests; $i++) {
+            $resp = $c->send($req, 10);
+            $response[] = $resp->value();
+        }
+        end_test($testName, 'https w. keep-alive', $response);
+        $c->xmlrpc_curl_handle = null;
+
+        begin_test($testName, 'https multicall');
+        $response = $c->send($reqs);
+        foreach ($response as $key => & $val) {
+            $val = $val->value();
+        }
+        end_test($testName, 'https multicall', $response);
+
+        if (function_exists('gzinflate')) {
+            $c->accepted_compression = array('gzip');
+            $c->request_compression = 'gzip';
+
+            $c->keepalive = false;
+            begin_test($testName, 'https w. compression and no keepalive');
+            $response = array();
+            for ($i = 0; $i < $num_tests; $i++) {
+                $resp = $c->send($req);
+                $response[] = $resp->value();
+            }
+            end_test($testName, 'https w. compression and no keepalive', $response);
+
+            $c->keepalive = true;
+            begin_test($testName, 'https w. keep-alive and compression');
+            $response = array();
+            for ($i = 0; $i < $num_tests; $i++) {
+                $resp = $c->send($req, 10);
+                $response[] = $resp->value();
+            }
+            end_test($testName, 'https w. keep-alive and compression', $response);
+            $c->xmlrpc_curl_handle = null;
+
+            begin_test($testName, 'multicall w. https and compression');
+            $response = $c->send($reqs);
+            foreach ($response as $key => & $val) {
+                $val = $val->value();
+            }
+            end_test($testName, 'multicall w. https and compression', $response);
+        }
+    }
+
+    if (function_exists('curl_init') && defined('CURL_HTTP_VERSION_2_0')) {
+
+        /// test multicall vs. many calls vs. keep-alives - HTTP/2
+
+        $server = explode(':', $args['HTTPSSERVER']);
+        if (count($server) > 1) {
+            $srv = 'https://' . $server[0] . ':' . $server[1] . $args['HTTPSURI'];
+            $c = new Client($args['HTTPSURI'], $server[0], $server[1], 'https');
+        } else {
+            $srv = 'https://' . $args['HTTPSSERVER'] . $args['HTTPSURI'];
+            $c = new Client($args['HTTPSURI'], $args['HTTPSSERVER'], 443, 'h2');
+        }
+        $c->setSSLVerifyPeer(!$args['HTTPSIGNOREPEER']);
+        $c->setSSLVerifyHost($args['HTTPSVERIFYHOST']);
+        // do not interfere with http compression
+        $c->setAcceptedCompression(false);
+        //$c->debug = 1;
+
+        $testName = "Repeated send (small array) to $srv - HTTP/2";
+
+        begin_test($testName, 'http2 no keep-alive');
+        $c->keepalive = false;
+        $response = array();
+        for ($i = 0; $i < $num_tests; $i++) {
+            $resp = $c->send($req);
+            $response[] = $resp->value();
+        }
+        end_test($testName, 'http2 no keep-alive', $response);
+
+        begin_test($testName, 'http2 w. keep-alive');
+        $c->keepalive = true;
+        $response = array();
+        for ($i = 0; $i < $num_tests; $i++) {
+            $resp = $c->send($req, 10);
+            $response[] = $resp->value();
+        }
+        end_test($testName, 'http2 w. keep-alive', $response);
+        $c->xmlrpc_curl_handle = null;
+
+        begin_test($testName, 'http2 multicall');
+        $response = $c->send($reqs);
+        foreach ($response as $key => & $val) {
+            $val = $val->value();
+        }
+        end_test($testName, 'http2 multicall', $response);
+
+        if (function_exists('gzinflate')) {
+            $c->accepted_compression = array('gzip');
+            $c->request_compression = 'gzip';
+
+            $c->keepalive = false;
+            begin_test($testName, 'http2 w. compression and no keepalive');
+            $response = array();
+            for ($i = 0; $i < $num_tests; $i++) {
+                $resp = $c->send($req);
+                $response[] = $resp->value();
+            }
+            end_test($testName, 'http2 w. compression and no keepalive', $response);
+
+            $c->keepalive = true;
+            begin_test($testName, 'http2 w. keep-alive and compression');
+            $response = array();
+            for ($i = 0; $i < $num_tests; $i++) {
+                $resp = $c->send($req, 10);
+                $response[] = $resp->value();
+            }
+            end_test($testName, 'http2 w. keep-alive and compression', $response);
+            $c->xmlrpc_curl_handle = null;
+
+            begin_test($testName, 'multicall w. http2 and compression');
+            $response = $c->send($reqs);
+            foreach ($response as $key => & $val) {
+                $val = $val->value();
+            }
+            end_test($testName, 'multicall w. http2 and compression', $response);
+        }
+    }
 } // end of 'if no xdebug profiling'
 
 
index 388d481..c9c6297 100644 (file)
@@ -138,16 +138,16 @@ class Client
      *                     e.g. /xmlrpc/server.php
      *                     e.g. http://phpxmlrpc.sourceforge.net/server.php
      *                     e.g. https://james:bond@secret.service.com:444/xmlrpcserver?agent=007
-     *                     e.g. http2tls://fast-and-secure-services.org/endpoint
+     *                     e.g. h2://fast-and-secure-services.org/endpoint
      * @param string $server the server name / ip address
      * @param integer $port the port the server is listening on, when omitted defaults to 80 or 443 depending on
      *                      protocol used
-     * @param string $method the http protocol variant: defaults to 'http'; 'https', 'http11', 'http2tls' and 'http2' can
+     * @param string $method the http protocol variant: defaults to 'http'; 'https', 'http11', 'h2' and 'h2c' can
      *                       be used if CURL is installed. The value set here can be overridden in any call to $this->send().
-     *                       Use 'http2tls' to make the lib attempt to use http/2 over a secure connection, and 'http2'
-     *                       for http/2 without tls. Note that 'http2' will not use the h2c 'upgrade' method, and be
+     *                       Use 'h2' to make the lib attempt to use http/2 over a secure connection, and 'h2c'
+     *                       for http/2 without tls. Note that 'h2c' will not use the h2c 'upgrade' method, and be
      *                       thus incompatible with any server/proxy not supporting http/2. This is because POST
-     *                       request are not compatible with h2c.
+     *                       request are not compatible with h2c upgrade.
      */
     public function __construct($path, $server = '', $port = '', $method = '')
     {
@@ -481,12 +481,12 @@ class Client
      *                         This timeout value is passed to fsockopen(). It is also used for detecting server
      *                         timeouts during communication (i.e. if the server does not send anything to the client
      *                         for $timeout seconds, the connection will be closed).
-     * @param string $method valid values are 'http', 'http11', 'https', 'http2tls' and 'http2'. If left unspecified,
+     * @param string $method valid values are 'http', 'http11', 'https', 'h2' and 'h2c'. If left unspecified,
      *                       the http protocol chosen during creation of the object will be used.
-     *                       Use 'http2tls' to make the lib attempt to use http/2 over a secure connection, and 'http2'
-     *                       for http/2 without tls. Note that 'http2' will not use the h2c 'upgrade' method, and be
+     *                       Use 'h2' to make the lib attempt to use http/2 over a secure connection, and 'h2c'
+     *                       for http/2 without tls. Note that 'h2c' will not use the h2c 'upgrade' method, and be
      *                       thus incompatible with any server/proxy not supporting http/2. This is because POST
-     *                       request are not compatible with h2c.
+     *                       request are not compatible with h2c upgrade.
      *
      * @return Response|Response[] Note that the client will always return a Response object, even if the call fails
      * @todo allow throwing exceptions instead of returning responses in case of failed calls and/or Fault responses
@@ -516,7 +516,7 @@ class Client
         /// @todo we could be smarter about this and force usage of curl in scenarios where it is both available and
         ///       needed, such as digest or ntlm auth. Do not attempt to use it for https if not present
         $useCurl = ($this->use_curl == self::USE_CURL_ALWAYS) || ($this->use_curl == self::USE_CURL_AUTO &&
-            (in_array($method, array('https', 'http11', 'http2', 'http2tls'))));
+            (in_array($method, array('https', 'http11', 'h2c', 'h2'))));
 
         if ($useCurl) {
             $r = $this->sendPayloadCURL(
@@ -869,7 +869,7 @@ class Client
      * @param string $proxyUsername
      * @param string $proxyPassword
      * @param int $proxyAuthType
-     * @param string $method 'http' (let curl decide), 'http10', 'http11', 'https', 'http2' or 'http2tls'
+     * @param string $method 'http' (let curl decide), 'http10', 'http11', 'https', 'h2c' or 'h2'
      * @param bool $keepAlive
      * @param string $key
      * @param string $keyPass
@@ -885,7 +885,7 @@ class Client
             $this->errstr = 'CURL unavailable on this install';
             return new Response(0, PhpXmlRpc::$xmlrpcerr['no_curl'], PhpXmlRpc::$xmlrpcstr['no_curl']);
         }
-        if ($method == 'https' || $method == 'http2tls') {
+        if ($method == 'https' || $method == 'h2') {
             // q: what about installs where we get back a string, but curl is linked to other ssl libs than openssl?
             if (($info = curl_version()) &&
                 ((is_string($info) && strpos($info, 'OpenSSL') === null) || (is_array($info) && !isset($info['ssl_version'])))
@@ -894,14 +894,14 @@ class Client
                 return new Response(0, PhpXmlRpc::$xmlrpcerr['no_ssl'], PhpXmlRpc::$xmlrpcstr['no_ssl']);
             }
         }
-        if (($method == 'http2tls' && !defined('CURL_HTTP_VERSION_2_0')) ||
-            ($method == 'http2' && !defined('CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE'))) {
+        if (($method == 'h2' && !defined('CURL_HTTP_VERSION_2_0')) ||
+            ($method == 'h2c' && !defined('CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE'))) {
             $this->errstr = 'HTTP/2 unavailable on this install';
             return new Response(0, PhpXmlRpc::$xmlrpcerr['no_http2'], PhpXmlRpc::$xmlrpcstr['no_http2']);
         }
 
         if ($port == 0) {
-            if (in_array($method, array('http', 'http10', 'http11', 'http2'))) {
+            if (in_array($method, array('http', 'http10', 'http11', 'h2c'))) {
                 $port = 80;
             } else {
                 $port = 443;
@@ -938,10 +938,10 @@ class Client
         }
 
         if (!$keepAlive || !$this->xmlrpc_curl_handle) {
-            if ($method == 'http11' || $method == 'http10' || $method == 'http2') {
+            if ($method == 'http11' || $method == 'http10' || $method == 'h2c') {
                 $protocol = 'http';
             } else {
-                if ($method == 'http2tls') {
+                if ($method == 'h2') {
                     $protocol = 'https';
                 } else {
                     $protocol = $method;
@@ -1010,10 +1010,10 @@ class Client
             case 'http11':
                 curl_setopt($curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
                 break;
-            case 'http2':
+            case 'h2c':
                 curl_setopt($curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE);
                 break;
-            case 'http2tls':
+            case 'h2':
                 curl_setopt($curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
                 break;
         }
@@ -1027,7 +1027,7 @@ class Client
             }
         }
 
-        if ($method == 'https' || $method == 'http2tls') {
+        if ($method == 'https' || $method == 'h2') {
             // set cert file
             if ($cert) {
                 curl_setopt($curl, CURLOPT_SSLCERT, $cert);
@@ -1184,6 +1184,7 @@ class Client
         if ($fallback) {
             // system.multicall is (probably) unsupported by server:
             // emulate multicall via multiple requests
+            /// @todo use curl multi_ functions to make this quicker
             foreach ($reqs as $req) {
                 $results[] = $this->send($req, $timeout, $method);
             }
index 3ac1948..a6bb949 100644 (file)
@@ -321,8 +321,8 @@ class HTTPTest extends ServerTest
             return;
         }
 
-        $this->method = 'http2'; // not an error the double assignment!
-        $this->client->method = 'http2';
+        $this->method = 'h2c'; // not an error the double assignment!
+        $this->client->method = 'h2c';
         //$this->client->keepalive = false; // q: is this a good idea?
 
         $this->expectHttp2 = true;
@@ -351,8 +351,8 @@ class HTTPTest extends ServerTest
         }
 
         $this->client->server = $this->args['HTTPSSERVER'];
-        $this->method = 'http2tls';
-        $this->client->method = 'http2tls';
+        $this->method = 'h2';
+        $this->client->method = 'h2';
         $this->client->path = $this->args['HTTPSURI'];
         $this->client->setSSLVerifyPeer(!$this->args['HTTPSIGNOREPEER']);
         $this->client->setSSLVerifyHost($this->args['HTTPSVERIFYHOST']);