From 377ed2ed8db7bcfc49940b18e897b87222db76be Mon Sep 17 00:00:00 2001 From: epriestley Date: Tue, 14 Apr 2020 16:39:15 -0700 Subject: [PATCH] If the Conduit server asserts it has the "gzip" capability, compress requests Summary: Ref T13507. For various messy reasons we can't blindly assume the server supports "gzip" -- but if the server tells us it does, we're on firmer ground. If the server returns an "X-Conduit-Capabilities: gzip" header and we have compression support locally, compress subsequent requests. This restores D21073, which was reverted by D21076. Test Plan: With a gzip-asserting server, added debugging code and ran various "arc" commands. Saw the 2nd..Nth calls hit compression code. Maniphest Tasks: T13507 Differential Revision: https://secure.phabricator.com/D21119 --- src/conduit/ConduitClient.php | 24 +++++++++++++++++++++++- src/conduit/ConduitFuture.php | 14 ++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/conduit/ConduitClient.php b/src/conduit/ConduitClient.php index 065a42ab..441fe25c 100644 --- a/src/conduit/ConduitClient.php +++ b/src/conduit/ConduitClient.php @@ -13,6 +13,7 @@ final class ConduitClient extends Phobject { private $privateKey; private $conduitToken; private $oauthToken; + private $capabilities = array(); const AUTH_ASYMMETRIC = 'asymmetric'; @@ -86,6 +87,11 @@ final class ConduitClient extends Phobject { return $this; } + public function enableCapabilities(array $capabilities) { + $this->capabilities += array_fuse($capabilities); + return $this; + } + public function callMethod($method, array $params) { $meta = array(); @@ -143,12 +149,28 @@ final class ConduitClient extends Phobject { // Always use the cURL-based HTTPSFuture, for proxy support and other // protocol edge cases that HTTPFuture does not support. - $core_future = new HTTPSFuture($uri, $data); + $core_future = new HTTPSFuture($uri); $core_future->addHeader('Host', $this->getHostStringForHeader()); $core_future->setMethod('POST'); $core_future->setTimeout($this->timeout); + // See T13507. If possible, try to compress requests. To compress requests, + // we must have "gzencode()" available and the server needs to have + // asserted it has the "gzip" capability. + $can_gzip = + (function_exists('gzencode')) && + (isset($this->capabilities['gzip'])); + if ($can_gzip) { + $gzip_data = phutil_build_http_querystring($data); + $gzip_data = gzencode($gzip_data); + + $core_future->addHeader('Content-Encoding', 'gzip'); + $core_future->setData($gzip_data); + } else { + $core_future->setData($data); + } + if ($this->username !== null) { $core_future->setHTTPBasicAuthCredentials( $this->username, diff --git a/src/conduit/ConduitFuture.php b/src/conduit/ConduitFuture.php index f6c192b6..20c6906a 100644 --- a/src/conduit/ConduitFuture.php +++ b/src/conduit/ConduitFuture.php @@ -3,6 +3,7 @@ final class ConduitFuture extends FutureProxy { private $client; + private $engine; private $conduitMethod; private $profilerCallID; @@ -40,6 +41,19 @@ final class ConduitFuture extends FutureProxy { throw $status; } + $capabilities = array(); + foreach ($headers as $header) { + list($name, $value) = $header; + if (!strcasecmp($name, 'X-Conduit-Capabilities')) { + $capabilities = explode(' ', $value); + break; + } + } + + if ($capabilities) { + $this->client->enableCapabilities($capabilities); + } + $raw = $body; $shield = 'for(;;);';