Skip to content

Commit

Permalink
Add hostname replacement support and additional options for long runn…
Browse files Browse the repository at this point in the history
…ers (#5)

* Increase long runner timeout

* Add host replacement support for orch sites and option support for callback payloads

* Fix psalm
  • Loading branch information
acharron-hl authored Apr 10, 2024
1 parent 81cb61c commit ce0cdb5
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 6 deletions.
5 changes: 5 additions & 0 deletions psalm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@
<directory name="src" />
</errorLevel>
</PropertyNotSetInConstructor>
<RiskyTruthyFalsyComparison>
<errorLevel type="suppress">
<directory name="src" />
</errorLevel>
</RiskyTruthyFalsyComparison>
</issueHandlers>
<projectFiles>
<directory name="src"/>
Expand Down
13 changes: 8 additions & 5 deletions src/Clients/SiteHttpClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public function withNoAuth(): SiteHttpClient
/**
* Run a callback payload from a long-runner response.
*/
public function runCallbackPayload(string $callbackPayload): HttpResponse
public function runCallbackPayload(string $callbackPayload, array $options = []): HttpResponse
{
// Clear the default auth header.
$response = $this->withNoAuth()->post(
Expand All @@ -77,10 +77,13 @@ public function runCallbackPayload(string $callbackPayload): HttpResponse
[
"content-type" => "application/system+jwt",
],
[
"timeout" => 25,
"throw" => false,
],
array_merge(
[
"timeout" => 30,
"throw" => false,
],
$options,
),
);
return $response;
}
Expand Down
80 changes: 79 additions & 1 deletion src/Orch/OrchSite.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@

namespace Garden\Sites\Orch;

use Garden\Http\HttpHandlerInterface;
use Garden\Http\HttpRequest;
use Garden\Http\HttpResponse;
use Garden\Sites\Clients\SiteHttpClient;
use Garden\Sites\Cluster;
use Garden\Sites\Site;
use Garden\Sites\SiteRecord;
use Garden\Utils\ArrayUtils;
Expand All @@ -28,6 +31,33 @@ public function __construct(SiteRecord $siteRecord, OrchSiteProvider $siteProvid
parent::__construct($siteRecord, $siteProvider);
}

/**
* Add additional default cookies to requests.
*
* @return SiteHttpClient
*/
public function httpClient(): SiteHttpClient
{
$httpClient = parent::httpClient();
$realHostname = $this->getRealHostName();
$clusterRouterHostname = $this->getClusterRouterHostname();
if ($clusterRouterHostname) {
$kludgedBaseUrl = $this->replaceHostnameInUrl($this->getBaseUrl());
$httpClient->setBaseUrl($kludgedBaseUrl);
$httpClient->setDefaultHeader("Host", $realHostname);

$httpClient->addMiddleware(function (HttpRequest $request, callable $next) use (
$realHostname
): HttpResponse {
$request->setUrl($this->replaceHostnameInUrl($request->getUrl()));
$request->setHeader("Host", $realHostname);
return $next($request);
});
}

return $httpClient;
}

/**
* @inheritDoc
*/
Expand All @@ -42,4 +72,52 @@ protected function loadSiteConfig(): array
});
return $mergedConfig;
}

/**
* Given a url, try to replace it's base url so it routes with the cluster router.
*
* @param string $url
* @return string
*/
public function replaceHostnameInUrl(string $url): string
{
$clusterRouterHostname = $this->getClusterRouterHostname();
if ($clusterRouterHostname === null) {
return $url;
}

$realHostname = $this->getRealHostName();
$kludgedUrl = str_replace($realHostname, $clusterRouterHostname, $url);
$kludgedUrl = str_replace("https", "http", $kludgedUrl);
return $kludgedUrl;
}

/**
* @return string
*/
private function getRealHostName(): string
{
$baseUrl = $this->getBaseUrl();
$realHostname = parse_url($baseUrl, PHP_URL_HOST);
return $realHostname;
}

/**
* @return string|null
*/
public function getClusterRouterHostname(): ?string
{
switch ($this->getCluster()->getRegionID()) {
case Cluster::REGION_AMS1_PROD1:
return "haproxy-router.ams1-routing-prod1.vanilladev.com";
case Cluster::REGION_SJC1_PROD1:
return "haproxy-router.sjc1-routing-prod1.vanilladev.com";
case Cluster::REGION_YUL1_PROD1:
return "haproxy-router.yul1-routing-prod1.vanilladev.com";
case Cluster::REGION_YUL1_DEV1:
return "haproxy-router.yul1-routing-dev1.vanilladev.com";
}

return null;
}
}
11 changes: 11 additions & 0 deletions src/SiteRecord.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
namespace Garden\Sites;

use Garden\Utils\ArrayUtils;
use Psr\Http\Message\UriInterface;
use Slim\Psr7\Factory\UriFactory;

/**
* Class holding a minimum of amount of data identifying a site.
Expand Down Expand Up @@ -89,6 +91,15 @@ public function getBaseUrl(): string
return $this->baseUrl;
}

/**
* @return UriInterface
*/
public function getBaseUri(): UriInterface
{
$uriFactory = new UriFactory();
return $uriFactory->createUri($this->getBaseUrl());
}

/**
* Set an extra meta value on the site record.
*
Expand Down
27 changes: 27 additions & 0 deletions tests/OrchSitesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,33 @@ public function expectedSites(): array
];
}

/**
* Overridden because we use the haproxies.
* @param ExpectedSite $expectedSite
*
* @return void
* @dataProvider provideExpectedSites
*/
public function testSiteClientBaseUrl(ExpectedSite $expectedSite)
{
$provider = $this->siteProvider();
$provider->setRegionIDs([$expectedSite->expectedRegionID]);
$site = $provider->getSite($expectedSite->getSiteID());
$siteClient = $site->httpClient();
$siteClient->setThrowExceptions(false);

$mockHandler = new MockHttpHandler();
$siteClient->setHandler($mockHandler);

// Base URL is added.
$response = $siteClient->get("/hello-world");
$this->assertEquals(
$site->replaceHostnameInUrl("{$expectedSite->getBaseUrl()}/hello-world"),
$response->getRequest()->getUrl(),
);
$this->assertEquals($expectedSite->getBaseUri()->getHost(), $response->getRequest()->getHeader("host"));
}

/**
* @inheritDoc
*/
Expand Down

0 comments on commit ce0cdb5

Please sign in to comment.