From: gggeek Date: Thu, 26 May 2022 22:09:28 +0000 (+0000) Subject: change names of options used for http/2; add https and http/2 tests to benchmark.php X-Git-Tag: 4.7.2 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=0336f44b51a40b674ef93c35529373d2225b5f1d;p=plcapi.git change names of options used for http/2; add https and http/2 tests to benchmark.php --- diff --git a/NEWS b/NEWS index 89026ee4..aabea24e 100644 --- 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 diff --git a/extras/benchmark.php b/extras/benchmark.php index 2f0f55a2..baeb23b9 100644 --- a/extras/benchmark.php +++ b/extras/benchmark.php @@ -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' diff --git a/src/Client.php b/src/Client.php index 388d481e..c9c62975 100644 --- a/src/Client.php +++ b/src/Client.php @@ -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); } diff --git a/tests/6HTTPTest.php b/tests/6HTTPTest.php index 3ac19486..a6bb9494 100644 --- a/tests/6HTTPTest.php +++ b/tests/6HTTPTest.php @@ -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']);