Skip to content

Commit

Permalink
switch to http/2 prior-knowledge for non-tls requests
Browse files Browse the repository at this point in the history
  • Loading branch information
gggeek committed May 26, 2022
1 parent cbba096 commit 09dbc14
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 19 deletions.
9 changes: 9 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
@@ -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`.
Expand Down
31 changes: 18 additions & 13 deletions src/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -137,16 +137,17 @@ public static function setLogger($logger)
* 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:[email protected]:443/xmlrpcserver?agent=007
* e.g. http2tls://fast-and-secure-services/endpoint
* e.g. https://james:[email protected]: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 = '')
{
Expand Down Expand Up @@ -480,11 +481,12 @@ public function setUserAgent($agentString)
* 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
Expand Down Expand Up @@ -883,14 +885,17 @@ protected function sendPayloadCURL($req, $server, $port, $timeout = 0, $username
$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']);
}
Expand Down Expand Up @@ -1006,7 +1011,7 @@ protected function sendPayloadCURL($req, $server, $port, $timeout = 0, $username
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);
Expand Down
2 changes: 1 addition & 1 deletion src/PhpXmlRpc.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
9 changes: 4 additions & 5 deletions tests/6HTTPTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ public function testHttp2($method)
{
$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;
Expand All @@ -325,10 +325,9 @@ public function testHttp2($method)
$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;
}

/**
Expand All @@ -345,7 +344,7 @@ public function testHttp2tls($method)
{
$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;
Expand Down

0 comments on commit 09dbc14

Please sign in to comment.