Skip to content

Commit

Permalink
Utilizing more of the Guzzle request options, allowing for
Browse files Browse the repository at this point in the history
additional Consul envvars to be used.

- Client::__construct now concatenates custom configuration with default
  to prevent requiring entirely verbose config array definition.
  • Loading branch information
dcarbone committed May 10, 2017
1 parent d354a71 commit c54eb76
Show file tree
Hide file tree
Showing 5 changed files with 185 additions and 46 deletions.
22 changes: 12 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,18 @@ You may alternatively define values yourself:

```php
$config = new \DCarbone\PHPConsulAPI\Config([
'HttpClient' => $client // REQUIRED Client conforming to GuzzleHttp\ClientInterface

'Address' => 'address of server', // REQUIRED
'Scheme' => 'http or https', // REQUIRED
'Datacenter' => 'name of datacenter', // OPTIONAL
'HttpAuth' => 'user:pass', // OPTIONAL,
'WaitTime' => 30, // OPTIONAL, not used yet
'Token' => 'auth token', // OPTIONAL
'TokenInHeader' => false // OPTIONAL
'InsecureSkipVerify' => false, // OPTIONAL
'HttpClient' => $client // [required] Client conforming to GuzzleHttp\ClientInterface
'Address' => 'address of server', // [required]

'Scheme' => 'http or https', // [optional] defaults to "http"
'Datacenter' => 'name of datacenter', // [optional]
'HttpAuth' => 'user:pass', // [optional]
'Token' => 'auth token', // [optional] default auth token to use
'TokenInHeader' => false, // [optional] specifies whether to send the token in the header or query string
'InsecureSkipVerify' => false, // [optional] if set to true, ignores all SSL validation
'CAFile' => '', // [optional] path to ca cert file, see http://docs.guzzlephp.org/en/latest/request-options.html#verify
'CertFile' => '', // [optional] path to client pem. if set, requires KeyFile also be set
'KeyFile' => '', // [optional] path to client
]);
```

Expand Down
6 changes: 1 addition & 5 deletions src/AbstractClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,7 @@ protected function doRequest(Request $r) {
try {
// If we actually have a client defined...
if (isset($this->c->HttpClient) && $this->c->HttpClient instanceof ClientInterface) {
$response = $this->c->HttpClient->send($r->toPsrRequest(), [
'http_errors' => false,
'verify' => $this->c->isInsecureSkipVerify(),
'decode_content' => false,
]);
$response = $this->c->HttpClient->send($r->toPsrRequest(), $this->c->getGuzzleRequestOptions());
} // Otherwise, throw error to be caught below
else {
throw new \RuntimeException('Unable to execute query as no HttpClient has been defined.');
Expand Down
190 changes: 161 additions & 29 deletions src/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/
use GuzzleHttp\Client;
use GuzzleHttp\ClientInterface;
use GuzzleHttp\RequestOptions;

/**
* Class Config
Expand Down Expand Up @@ -65,6 +66,27 @@ class Config {
*/
public $Token = '';

/**
* Optional path to CA certificate
*
* @var string
*/
public $CAFile = '';

/**
* Optional path to certificate. If set, KeyFile must also be set
*
* @var string
*/
public $CertFile = '';

/**
* Optional path to private key. If set, CertFile must also be set
*
* @var string
*/
public $KeyFile = '';

/**
* Whether to skip SSL validation. This does nothing unless you use it within your HttpClient of choice.
*
Expand All @@ -91,13 +113,25 @@ class Config {
* @param array $config
*/
public function __construct(array $config = []) {
foreach ($config as $k => $v) {
foreach ($config + self::getDefaultConfig() as $k => $v) {
$this->{"set{$k}"}($v);
}

if (null !== $this->HttpAuth && !isset($this->HttpAuth)) {
$this->HttpAuth = new HttpAuth();
}

// quick validation on key/cert combo
$c = $this->getCertFile();
$k = $this->getKeyFile();
if (('' !== $k && '' === $c) || ('' !== $c && '' === $k)) {
throw new \InvalidArgumentException(sprintf(
'%s - CertFile and KeyFile must be both either empty or populated. Key: %s; Cert: %s',
get_class($this),
$k,
$c
));
}
}

/**
Expand All @@ -106,34 +140,53 @@ public function __construct(array $config = []) {
* @return \DCarbone\PHPConsulAPI\Config
*/
public static function newDefaultConfig() {
$conf = new static([
return new static(self::getDefaultConfig());
}

/**
* @return array
*/
private static function getDefaultConfig() {
$conf = [
'Address' => '127.0.0.1:8500',
'Scheme' => 'http',
]);

$envParams = static::getEnvironmentConfig();
if (isset($envParams[Consul::HTTPAddrEnvName])) {
$conf->setAddress($envParams[Consul::HTTPAddrEnvName]);
}

if (isset($envParams[Consul::HTTPTokenEnvName])) {
$conf->setToken($envParams[Consul::HTTPTokenEnvName]);
}

if (isset($envParams[Consul::HTTPAuthEnvName])) {
$conf->setHttpAuth($envParams[Consul::HTTPAuthEnvName]);
}

if (isset($envParams[Consul::HTTPSSLEnvName]) && $envParams[Consul::HTTPSSLEnvName]) {
$conf->setScheme('https');
}

if (isset($envParams[Consul::HTTPSSLVerifyEnvName]) && !$envParams[Consul::HTTPSSLVerifyEnvName]) {
$conf->setInsecureSkipVerify(false);
'HttpClient' => new Client(),
];

// parse env vars
foreach (static::getEnvironmentConfig() as $k => $v) {
switch ($k) {
case Consul::HTTPAddrEnvName:
$conf['Address'] = $v;
break;
case Consul::HTTPTokenEnvName:
$conf['Token'] = $v;
break;
case Consul::HTTPAuthEnvName:
$conf['HttpAuth'] = $v;
break;
case Consul::HTTPCAFileEnvName:
$conf['CAFile'] = $v;
break;
case Consul::HTTPClientCertEnvName:
$conf['CertFile'] = $v;
break;
case Consul::HTTPClientKeyEnvName:
$conf['KeyFile'] = $v;
break;
case Consul::HTTPSSLEnvName:
if ((bool)$v) {
$conf['Scheme'] = 'https';
}
break;
case Consul::HTTPSSLVerifyEnvName:
if ((bool)$v) {
$conf['InsecureSkipVerify'] = true;
}
break;
}
}

$conf->setHttpClient(new Client());

return $conf;
}

Expand Down Expand Up @@ -269,6 +322,54 @@ public function setHttpAuth($HttpAuth) {
));
}

/**
* @return string
*/
public function getCAFile() {
return $this->CAFile;
}

/**
* @param string $CAFile
* @return \DCarbone\PHPConsulAPI\Config
*/
public function setCAFile($CAFile) {
$this->CAFile = $CAFile;
return $this;
}

/**
* @return string
*/
public function getCertFile() {
return $this->CertFile;
}

/**
* @param string $CertFile
* @return \DCarbone\PHPConsulAPI\Config
*/
public function setCertFile($CertFile) {
$this->CertFile = $CertFile;
return $this;
}

/**
* @return string
*/
public function getKeyFile() {
return $this->KeyFile;
}

/**
* @param string $KeyFile
* @return \DCarbone\PHPConsulAPI\Config
*/
public function setKeyFile($KeyFile) {
$this->KeyFile = $KeyFile;
return $this;
}

/**
* @return \GuzzleHttp\ClientInterface
*/
Expand Down Expand Up @@ -319,15 +420,42 @@ public function intToMillisecond($in) {
return sprintf('%dms', $ms);
}

/**
* @return array
*/
public function getGuzzleRequestOptions() {
// TODO: Define once?
$opts = [
RequestOptions::HTTP_ERRORS => false,
RequestOptions::DECODE_CONTENT => false,
];

if (!$this->isInsecureSkipVerify()) {
$opts[RequestOptions::VERIFY] = false;
} else if ('' !== ($b = $this->getCAFile())) {
$opts[RequestOptions::VERIFY] = $b;
}

if ('' !== ($c = $this->getCertFile())) {
$opts[RequestOptions::CERT] = $c;
$opts[RequestOptions::SSL_KEY] = $this->getKeyFile();
}

return $opts;
}

/**
* @return array
*/
public static function getEnvironmentConfig() {
return array_filter([
'CONSUL_HTTP_ADDR' => static::_tryGetEnvParam('CONSUL_HTTP_ADDR'),
'CONSUL_HTTP_AUTH' => static::_tryGetEnvParam('CONSUL_HTTP_AUTH'),
'CONSUL_HTTP_SSL' => static::_tryGetEnvParam('CONSUL_HTTP_SSL'),
'CONSUL_HTTP_SSL_VERIFY' => static::_tryGetEnvParam('CONSUL_HTTP_SSL_VERIFY')
Consul::HTTPAddrEnvName => static::_tryGetEnvParam(Consul::HTTPAddrEnvName),
Consul::HTTPAuthEnvName => static::_tryGetEnvParam(Consul::HTTPAuthEnvName),
Consul::HTTPCAFileEnvName => static::_tryGetEnvParam(Consul::HTTPCAFileEnvName),
Consul::HTTPClientCertEnvName => static::_tryGetEnvParam(Consul::HTTPClientCertEnvName),
Consul::HTTPClientKeyEnvName => static::_tryGetEnvParam(Consul::HTTPClientKeyEnvName),
Consul::HTTPSSLEnvName => static::_tryGetEnvParam(Consul::HTTPSSLEnvName),
Consul::HTTPSSLVerifyEnvName => static::_tryGetEnvParam(Consul::HTTPSSLVerifyEnvName),
],
function ($val) {
return null !== $val;
Expand All @@ -339,6 +467,10 @@ function ($val) {
* @return string|null
*/
protected static function _tryGetEnvParam($param) {
if (isset($_ENV[$param])) {
return $_ENV[$param];
}

if (false !== ($value = getenv($param))) {
return $value;
}
Expand Down
3 changes: 3 additions & 0 deletions src/Consul.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ class Consul {
const HTTPAddrEnvName = 'CONSUL_HTTP_ADDR';
const HTTPTokenEnvName = 'CONSUL_HTTP_TOKEN';
const HTTPAuthEnvName = 'CONSUL_HTTP_AUTH';
const HTTPCAFileEnvName = "CONSUL_CACERT";
const HTTPClientCertEnvName = "CONSUL_CLIENT_CERT";
const HTTPClientKeyEnvName = "CONSUL_CLIENT_KEY";
const HTTPSSLEnvName = 'CONSUL_HTTP_SSL';
const HTTPSSLVerifyEnvName = 'CONSUL_HTTP_SSL_VERIFY';

Expand Down
10 changes: 8 additions & 2 deletions tests/Definition/ConfigDefinitionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,14 @@ class ConfigDefinitionTest extends AbstractDefinitionTestCases
/**
* @inheritDoc
*/
protected function getSubjectClassName()
{
protected function getSubjectClassName() {
return Config::class;
}

/**
* @return object
*/
protected function getEmptyInstance() {
return $this->createMock($this->getSubjectClassName());
}
}

0 comments on commit c54eb76

Please sign in to comment.