Skip to content

Commit

Permalink
Merge pull request #10 from dcarbone/feature/better-guzzle-integration
Browse files Browse the repository at this point in the history
Feature/better guzzle integration
  • Loading branch information
dcarbone authored May 10, 2017
2 parents d354a71 + 483a49a commit ca0978d
Show file tree
Hide file tree
Showing 5 changed files with 189 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
194 changes: 165 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,30 @@ 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
));
}

// if client hasn't been constructed, construct.
if (null === $this->HttpClient) {
$this->HttpClient = new Client();
}
}

/**
Expand All @@ -106,34 +145,52 @@ 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);
];

// 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 +326,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 +424,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 +471,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 ca0978d

Please sign in to comment.