mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-26 08:42:41 +01:00
Route internal conduit calls if other hosts available
Summary: Ref T2785 Looks for hosts in `conduit.servers` config and if any exist route any conduit calls through any one of the hosts. Test Plan: Make some curl calls to public methods (`conduit.ping`), watch the access log for two requests. Make some calls from the UI that require authentication, watch the access log a bit more. Also ran the unit tests. Reviewers: epriestley Reviewed By: epriestley CC: aran, Korvin Maniphest Tasks: T2785 Differential Revision: https://secure.phabricator.com/D5970
This commit is contained in:
parent
a1a46656cb
commit
94e7878a57
7 changed files with 118 additions and 14 deletions
|
@ -830,6 +830,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorChatLogQuery' => 'applications/chatlog/PhabricatorChatLogQuery.php',
|
'PhabricatorChatLogQuery' => 'applications/chatlog/PhabricatorChatLogQuery.php',
|
||||||
'PhabricatorConduitAPIController' => 'applications/conduit/controller/PhabricatorConduitAPIController.php',
|
'PhabricatorConduitAPIController' => 'applications/conduit/controller/PhabricatorConduitAPIController.php',
|
||||||
'PhabricatorConduitCertificateToken' => 'applications/conduit/storage/PhabricatorConduitCertificateToken.php',
|
'PhabricatorConduitCertificateToken' => 'applications/conduit/storage/PhabricatorConduitCertificateToken.php',
|
||||||
|
'PhabricatorConduitConfigOptions' => 'applications/conduit/config/PhabricatorConduitConfigOptions.php',
|
||||||
'PhabricatorConduitConnectionLog' => 'applications/conduit/storage/PhabricatorConduitConnectionLog.php',
|
'PhabricatorConduitConnectionLog' => 'applications/conduit/storage/PhabricatorConduitConnectionLog.php',
|
||||||
'PhabricatorConduitConsoleController' => 'applications/conduit/controller/PhabricatorConduitConsoleController.php',
|
'PhabricatorConduitConsoleController' => 'applications/conduit/controller/PhabricatorConduitConsoleController.php',
|
||||||
'PhabricatorConduitController' => 'applications/conduit/controller/PhabricatorConduitController.php',
|
'PhabricatorConduitController' => 'applications/conduit/controller/PhabricatorConduitController.php',
|
||||||
|
@ -2601,6 +2602,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorChatLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
'PhabricatorChatLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||||
'PhabricatorConduitAPIController' => 'PhabricatorConduitController',
|
'PhabricatorConduitAPIController' => 'PhabricatorConduitController',
|
||||||
'PhabricatorConduitCertificateToken' => 'PhabricatorConduitDAO',
|
'PhabricatorConduitCertificateToken' => 'PhabricatorConduitDAO',
|
||||||
|
'PhabricatorConduitConfigOptions' => 'PhabricatorApplicationConfigOptions',
|
||||||
'PhabricatorConduitConnectionLog' => 'PhabricatorConduitDAO',
|
'PhabricatorConduitConnectionLog' => 'PhabricatorConduitDAO',
|
||||||
'PhabricatorConduitConsoleController' => 'PhabricatorConduitController',
|
'PhabricatorConduitConsoleController' => 'PhabricatorConduitController',
|
||||||
'PhabricatorConduitController' => 'PhabricatorController',
|
'PhabricatorConduitController' => 'PhabricatorController',
|
||||||
|
|
|
@ -113,18 +113,33 @@ abstract class AphrontApplicationConfiguration {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$path = $request->getPath();
|
$path = $request->getPath();
|
||||||
$host = $request->getHost();
|
$host = $request->getHost();
|
||||||
$base_uri = PhabricatorEnv::getEnvConfig('phabricator.base-uri');
|
$base_uri = PhabricatorEnv::getEnvConfig('phabricator.base-uri');
|
||||||
$prod_uri = PhabricatorEnv::getEnvConfig('phabricator.production-uri');
|
$prod_uri = PhabricatorEnv::getEnvConfig('phabricator.production-uri');
|
||||||
$file_uri = PhabricatorEnv::getEnvConfig('security.alternate-file-domain');
|
$file_uri = PhabricatorEnv::getEnvConfig(
|
||||||
|
'security.alternate-file-domain');
|
||||||
|
$conduit_uris = PhabricatorEnv::getEnvConfig('conduit.servers');
|
||||||
|
|
||||||
|
$uris = array_merge(
|
||||||
|
array(
|
||||||
|
$base_uri,
|
||||||
|
$prod_uri,
|
||||||
|
$file_uri,
|
||||||
|
),
|
||||||
|
$conduit_uris);
|
||||||
|
|
||||||
|
$host_match = false;
|
||||||
|
foreach ($uris as $uri) {
|
||||||
|
if ($host === id(new PhutilURI($uri))->getDomain()) {
|
||||||
|
$host_match = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NOTE: If the base URI isn't defined yet, don't activate alternate
|
// NOTE: If the base URI isn't defined yet, don't activate alternate
|
||||||
// domains.
|
// domains.
|
||||||
if ($base_uri &&
|
if ($base_uri && !$host_match) {
|
||||||
$host != id(new PhutilURI($base_uri))->getDomain() &&
|
|
||||||
$host != id(new PhutilURI($prod_uri))->getDomain() &&
|
|
||||||
$host != id(new PhutilURI($file_uri))->getDomain()) {
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$blog = id(new PhameBlogQuery())
|
$blog = id(new PhameBlogQuery())
|
||||||
|
|
|
@ -13,10 +13,14 @@ final class ConduitCall {
|
||||||
private $method;
|
private $method;
|
||||||
private $request;
|
private $request;
|
||||||
private $user;
|
private $user;
|
||||||
|
private $servers;
|
||||||
|
private $forceLocal;
|
||||||
|
|
||||||
public function __construct($method, array $params) {
|
public function __construct($method, array $params) {
|
||||||
$this->method = $method;
|
$this->method = $method;
|
||||||
$this->handler = $this->buildMethodHandler($method);
|
$this->handler = $this->buildMethodHandler($method);
|
||||||
|
$this->servers = PhabricatorEnv::getEnvConfig('conduit.servers');
|
||||||
|
$this->forceLocal = false;
|
||||||
|
|
||||||
$invalid_params = array_diff_key(
|
$invalid_params = array_diff_key(
|
||||||
$params,
|
$params,
|
||||||
|
@ -27,6 +31,16 @@ final class ConduitCall {
|
||||||
implode("', '", array_keys($invalid_params)) . "'.");
|
implode("', '", array_keys($invalid_params)) . "'.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->servers) {
|
||||||
|
$current_host = AphrontRequest::getHTTPHeader('HOST');
|
||||||
|
foreach ($this->servers as $server) {
|
||||||
|
if ($current_host === id(new PhutilURI($server))->getDomain()) {
|
||||||
|
$this->forceLocal = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$this->request = new ConduitAPIRequest($params);
|
$this->request = new ConduitAPIRequest($params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,6 +53,15 @@ final class ConduitCall {
|
||||||
return $this->user;
|
return $this->user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setForceLocal($force_local) {
|
||||||
|
$this->forceLocal = $force_local;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function shouldForceLocal() {
|
||||||
|
return $this->forceLocal;
|
||||||
|
}
|
||||||
|
|
||||||
public function shouldRequireAuthentication() {
|
public function shouldRequireAuthentication() {
|
||||||
return $this->handler->shouldRequireAuthentication();
|
return $this->handler->shouldRequireAuthentication();
|
||||||
}
|
}
|
||||||
|
@ -64,7 +87,35 @@ final class ConduitCall {
|
||||||
$this->request->setUser($this->getUser());
|
$this->request->setUser($this->getUser());
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->handler->executeMethod($this->request);
|
if (!$this->shouldForceLocal() && $this->servers) {
|
||||||
|
$server = $this->pickRandomServer($this->servers);
|
||||||
|
$client = new ConduitClient($server);
|
||||||
|
$params = $this->request->getAllParameters();
|
||||||
|
|
||||||
|
$params["__conduit__"]["isProxied"] = true;
|
||||||
|
|
||||||
|
if ($this->handler->shouldRequireAuthentication()) {
|
||||||
|
$client->callMethodSynchronous(
|
||||||
|
'conduit.connect',
|
||||||
|
array(
|
||||||
|
'client' => 'PhabricatorConduit',
|
||||||
|
'clientVersion' => '1.0',
|
||||||
|
'user' => $this->getUser()->getUserName(),
|
||||||
|
'certificate' => $this->getUser()->getConduitCertificate(),
|
||||||
|
'__conduit__' => $params["__conduit__"],
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $client->callMethodSynchronous(
|
||||||
|
$this->method,
|
||||||
|
$params);
|
||||||
|
} else {
|
||||||
|
return $this->handler->executeMethod($this->request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function pickRandomServer($servers) {
|
||||||
|
return $servers[array_rand($servers)];
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function buildMethodHandler($method) {
|
protected function buildMethodHandler($method) {
|
||||||
|
|
|
@ -4,13 +4,15 @@ final class ConduitCallTestCase extends PhabricatorTestCase {
|
||||||
|
|
||||||
public function testConduitPing() {
|
public function testConduitPing() {
|
||||||
$call = new ConduitCall('conduit.ping', array());
|
$call = new ConduitCall('conduit.ping', array());
|
||||||
|
$call->setForceLocal(true);
|
||||||
$result = $call->execute();
|
$result = $call->execute();
|
||||||
|
|
||||||
$this->assertEqual(false, empty($result));
|
$this->assertEqual(false, empty($result));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testConduitAuth() {
|
public function testConduitAuth() {
|
||||||
$call = new ConduitCall('user.whoami', array());
|
$call = new ConduitCall('user.whoami', array(), true);
|
||||||
|
$call->setForceLocal(true);
|
||||||
|
|
||||||
$caught = null;
|
$caught = null;
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorConduitConfigOptions
|
||||||
|
extends PhabricatorApplicationConfigOptions {
|
||||||
|
|
||||||
|
public function getName() {
|
||||||
|
return pht("Conduit");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDescription() {
|
||||||
|
return pht("Configure conduit.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getOptions() {
|
||||||
|
return array(
|
||||||
|
$this->newOption("conduit.servers", "list<string>", array())
|
||||||
|
->setLocked(true)
|
||||||
|
->setSummary(pht("Servers that conduit can connect to."))
|
||||||
|
->setDescription(
|
||||||
|
pht(
|
||||||
|
"Set an array of servers where conduit can connect to. This is ".
|
||||||
|
"an advanced option. Don't touch this unless you know what you ".
|
||||||
|
"are doing."))
|
||||||
|
->addExample(
|
||||||
|
'["http://phabricator2.example.com/", '.
|
||||||
|
'"http://phabricator3.example.com/]"',
|
||||||
|
pht('Valid Setting')),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -35,7 +35,8 @@ final class PhabricatorConduitAPIController
|
||||||
$metadata = idx($params, '__conduit__', array());
|
$metadata = idx($params, '__conduit__', array());
|
||||||
unset($params['__conduit__']);
|
unset($params['__conduit__']);
|
||||||
|
|
||||||
$call = new ConduitCall($method, $params);
|
$call = new ConduitCall(
|
||||||
|
$method, $params, idx($metadata, 'isProxied', false));
|
||||||
|
|
||||||
$result = null;
|
$result = null;
|
||||||
|
|
||||||
|
|
|
@ -98,6 +98,7 @@ final class ConduitAPI_differential_finishpostponedlinters_Method
|
||||||
'diff_id' => $diff_id,
|
'diff_id' => $diff_id,
|
||||||
'name' => 'arc:lint',
|
'name' => 'arc:lint',
|
||||||
'data' => json_encode($messages)));
|
'data' => json_encode($messages)));
|
||||||
|
$call->setForceLocal(true);
|
||||||
$call->setUser($request->getUser());
|
$call->setUser($request->getUser());
|
||||||
$call->execute();
|
$call->execute();
|
||||||
$call = new ConduitCall(
|
$call = new ConduitCall(
|
||||||
|
@ -106,6 +107,7 @@ final class ConduitAPI_differential_finishpostponedlinters_Method
|
||||||
'diff_id' => $diff_id,
|
'diff_id' => $diff_id,
|
||||||
'name' => 'arc:lint-postponed',
|
'name' => 'arc:lint-postponed',
|
||||||
'data' => json_encode($postponed_linters)));
|
'data' => json_encode($postponed_linters)));
|
||||||
|
$call->setForceLocal(true);
|
||||||
$call->setUser($request->getUser());
|
$call->setUser($request->getUser());
|
||||||
$call->execute();
|
$call->execute();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue