From 09dbc14b4fe37eb2535e6f9d37e713c974d8a780 Mon Sep 17 00:00:00 2001 From: gggeek Date: Thu, 26 May 2022 10:41:40 +0000 Subject: [PATCH] switch to http/2 prior-knowledge for non-tls requests --- NEWS | 9 +++++++++ src/Client.php | 31 ++++++++++++++++++------------- src/PhpXmlRpc.php | 2 +- tests/6HTTPTest.php | 9 ++++----- 4 files changed, 32 insertions(+), 19 deletions(-) diff --git a/NEWS b/NEWS index 5a20e18e..89026ee4 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,14 @@ +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. + + 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`. diff --git a/src/Client.php b/src/Client.php index baaa9607..0e4fac51 100644 --- a/src/Client.php +++ b/src/Client.php @@ -137,16 +137,17 @@ class Client * should use and empty string for all other parameters) * e.g. /xmlrpc/server.php * e.g. http://phpxmlrpc.sourceforge.net/server.php - * e.g. https://james:bond@secret.service.com:443/xmlrpcserver?agent=007 - * e.g. http2tls://fast-and-secure-services/endpoint + * e.g. https://james:bond@secret.service.com:444/xmlrpcserver?agent=007 + * e.g. http2tls://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', 'http2' and 'http2tls' can + * @param string $method the http protocol variant: defaults to 'http'; 'https', 'http11', 'http2tls' and 'http2' can * be used if CURL is installed. The value set here can be overridden in any call to $this->send(). - * Use 'http2' to make the lib attempt to use http/2 without tls and 'http2tls' for secure http/2 - * (note that 'http2' will most likely not result in an http/2 connection in any case, as it - * seems that upgrading a POST request on the fly from http is hard or impossible) + * 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 + * thus incompatible with any server/proxy not supporting http/2. This is because POST + * request are not compatible with h2c. */ public function __construct($path, $server = '', $port = '', $method = '') { @@ -480,11 +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', 'http2' and 'http2tls'. If left unspecified, + * @param string $method valid values are 'http', 'http11', 'https', 'http2tls' and 'http2'. If left unspecified, * the http protocol chosen during creation of the object will be used. - * Use 'http2' to make the lib attempt to use http/2 without tls and 'http2tls' for secure http/2 - * (note that 'http2' will most likely not result in an http/2 connection in any case, as it - * seems that upgrading a POST request on the fly from http is hard or impossible) + * 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 + * thus incompatible with any server/proxy not supporting http/2. This is because POST + * request are not compatible with h2c. * * @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 @@ -883,14 +885,17 @@ class Client $this->errstr = 'CURL unavailable on this install'; return new Response(0, PhpXmlRpc::$xmlrpcerr['no_curl'], PhpXmlRpc::$xmlrpcstr['no_curl']); } - if ($method == 'https') { + if ($method == 'https' || $method == 'http2tls') { + // 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']))) ) { $this->errstr = 'SSL unavailable on this install'; return new Response(0, PhpXmlRpc::$xmlrpcerr['no_ssl'], PhpXmlRpc::$xmlrpcstr['no_ssl']); } - } elseif (($method == 'http2' || $method == 'http2tls') && !defined('CURL_HTTP_VERSION_2')) { + } + if (($method == 'http2tls' && !defined('CURL_HTTP_VERSION_2TLS')) || + ($method == 'http2' && !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']); } @@ -1006,7 +1011,7 @@ class Client curl_setopt($curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); break; case 'http2': - curl_setopt($curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2); + curl_setopt($curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE); break; case 'http2tls': curl_setopt($curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS); diff --git a/src/PhpXmlRpc.php b/src/PhpXmlRpc.php index e49c1eb2..901d1eb1 100644 --- a/src/PhpXmlRpc.php +++ b/src/PhpXmlRpc.php @@ -80,7 +80,7 @@ class PhpXmlRpc public static $xmlrpc_internalencoding = "UTF-8"; public static $xmlrpcName = "XML-RPC for PHP"; - public static $xmlrpcVersion = "4.7.0"; + public static $xmlrpcVersion = "4.7.1"; // let user errors start at 800 public static $xmlrpcerruser = 800; diff --git a/tests/6HTTPTest.php b/tests/6HTTPTest.php index a1c46552..fa013bbf 100644 --- a/tests/6HTTPTest.php +++ b/tests/6HTTPTest.php @@ -315,7 +315,7 @@ class HTTPTest extends ServerTest { $this->markTestSkipped('CURL missing: cannot test http/2'); return; - } else if (!defined('CURL_HTTP_VERSION_2')) + } else if (!defined('CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE')) { $this->markTestSkipped('CURL http/2 support missing: cannot test http/2'); return; @@ -325,10 +325,9 @@ class HTTPTest extends ServerTest $this->client->method = 'http2'; //$this->client->keepalive = false; // q: is this a good idea? - /// @todo we disable checking for HTTP2 on plain http calls, as that is unsupported for POST requests - //$this->expectHttp2 = true; + $this->expectHttp2 = true; $this->$method(); - //$this->expectHttp2 = false; + $this->expectHttp2 = false; } /** @@ -345,7 +344,7 @@ class HTTPTest extends ServerTest { $this->markTestSkipped('HTTPS SERVER definition missing: cannot test http/2 tls'); return; - } else if (!defined('CURL_HTTP_VERSION_2')) + } else if (!defined('CURL_HTTP_VERSION_2TLS')) { $this->markTestSkipped('CURL http/2 support missing: cannot test http/2 tls'); return; -- 2.47.0