Skip to content

Commit c54eb76

Browse files
committed
Utilizing more of the Guzzle request options, allowing for
additional Consul envvars to be used. - Client::__construct now concatenates custom configuration with default to prevent requiring entirely verbose config array definition.
1 parent d354a71 commit c54eb76

File tree

5 files changed

+185
-46
lines changed

5 files changed

+185
-46
lines changed

README.md

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,18 @@ You may alternatively define values yourself:
4848

4949
```php
5050
$config = new \DCarbone\PHPConsulAPI\Config([
51-
'HttpClient' => $client // REQUIRED Client conforming to GuzzleHttp\ClientInterface
52-
53-
'Address' => 'address of server', // REQUIRED
54-
'Scheme' => 'http or https', // REQUIRED
55-
'Datacenter' => 'name of datacenter', // OPTIONAL
56-
'HttpAuth' => 'user:pass', // OPTIONAL,
57-
'WaitTime' => 30, // OPTIONAL, not used yet
58-
'Token' => 'auth token', // OPTIONAL
59-
'TokenInHeader' => false // OPTIONAL
60-
'InsecureSkipVerify' => false, // OPTIONAL
51+
'HttpClient' => $client // [required] Client conforming to GuzzleHttp\ClientInterface
52+
'Address' => 'address of server', // [required]
53+
54+
'Scheme' => 'http or https', // [optional] defaults to "http"
55+
'Datacenter' => 'name of datacenter', // [optional]
56+
'HttpAuth' => 'user:pass', // [optional]
57+
'Token' => 'auth token', // [optional] default auth token to use
58+
'TokenInHeader' => false, // [optional] specifies whether to send the token in the header or query string
59+
'InsecureSkipVerify' => false, // [optional] if set to true, ignores all SSL validation
60+
'CAFile' => '', // [optional] path to ca cert file, see http://docs.guzzlephp.org/en/latest/request-options.html#verify
61+
'CertFile' => '', // [optional] path to client pem. if set, requires KeyFile also be set
62+
'KeyFile' => '', // [optional] path to client
6163
]);
6264
```
6365

src/AbstractClient.php

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,7 @@ protected function doRequest(Request $r) {
101101
try {
102102
// If we actually have a client defined...
103103
if (isset($this->c->HttpClient) && $this->c->HttpClient instanceof ClientInterface) {
104-
$response = $this->c->HttpClient->send($r->toPsrRequest(), [
105-
'http_errors' => false,
106-
'verify' => $this->c->isInsecureSkipVerify(),
107-
'decode_content' => false,
108-
]);
104+
$response = $this->c->HttpClient->send($r->toPsrRequest(), $this->c->getGuzzleRequestOptions());
109105
} // Otherwise, throw error to be caught below
110106
else {
111107
throw new \RuntimeException('Unable to execute query as no HttpClient has been defined.');

src/Config.php

Lines changed: 161 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
*/
1818
use GuzzleHttp\Client;
1919
use GuzzleHttp\ClientInterface;
20+
use GuzzleHttp\RequestOptions;
2021

2122
/**
2223
* Class Config
@@ -65,6 +66,27 @@ class Config {
6566
*/
6667
public $Token = '';
6768

69+
/**
70+
* Optional path to CA certificate
71+
*
72+
* @var string
73+
*/
74+
public $CAFile = '';
75+
76+
/**
77+
* Optional path to certificate. If set, KeyFile must also be set
78+
*
79+
* @var string
80+
*/
81+
public $CertFile = '';
82+
83+
/**
84+
* Optional path to private key. If set, CertFile must also be set
85+
*
86+
* @var string
87+
*/
88+
public $KeyFile = '';
89+
6890
/**
6991
* Whether to skip SSL validation. This does nothing unless you use it within your HttpClient of choice.
7092
*
@@ -91,13 +113,25 @@ class Config {
91113
* @param array $config
92114
*/
93115
public function __construct(array $config = []) {
94-
foreach ($config as $k => $v) {
116+
foreach ($config + self::getDefaultConfig() as $k => $v) {
95117
$this->{"set{$k}"}($v);
96118
}
97119

98120
if (null !== $this->HttpAuth && !isset($this->HttpAuth)) {
99121
$this->HttpAuth = new HttpAuth();
100122
}
123+
124+
// quick validation on key/cert combo
125+
$c = $this->getCertFile();
126+
$k = $this->getKeyFile();
127+
if (('' !== $k && '' === $c) || ('' !== $c && '' === $k)) {
128+
throw new \InvalidArgumentException(sprintf(
129+
'%s - CertFile and KeyFile must be both either empty or populated. Key: %s; Cert: %s',
130+
get_class($this),
131+
$k,
132+
$c
133+
));
134+
}
101135
}
102136

103137
/**
@@ -106,34 +140,53 @@ public function __construct(array $config = []) {
106140
* @return \DCarbone\PHPConsulAPI\Config
107141
*/
108142
public static function newDefaultConfig() {
109-
$conf = new static([
143+
return new static(self::getDefaultConfig());
144+
}
145+
146+
/**
147+
* @return array
148+
*/
149+
private static function getDefaultConfig() {
150+
$conf = [
110151
'Address' => '127.0.0.1:8500',
111152
'Scheme' => 'http',
112-
]);
113-
114-
$envParams = static::getEnvironmentConfig();
115-
if (isset($envParams[Consul::HTTPAddrEnvName])) {
116-
$conf->setAddress($envParams[Consul::HTTPAddrEnvName]);
117-
}
118-
119-
if (isset($envParams[Consul::HTTPTokenEnvName])) {
120-
$conf->setToken($envParams[Consul::HTTPTokenEnvName]);
121-
}
122-
123-
if (isset($envParams[Consul::HTTPAuthEnvName])) {
124-
$conf->setHttpAuth($envParams[Consul::HTTPAuthEnvName]);
125-
}
126-
127-
if (isset($envParams[Consul::HTTPSSLEnvName]) && $envParams[Consul::HTTPSSLEnvName]) {
128-
$conf->setScheme('https');
129-
}
130-
131-
if (isset($envParams[Consul::HTTPSSLVerifyEnvName]) && !$envParams[Consul::HTTPSSLVerifyEnvName]) {
132-
$conf->setInsecureSkipVerify(false);
153+
'HttpClient' => new Client(),
154+
];
155+
156+
// parse env vars
157+
foreach (static::getEnvironmentConfig() as $k => $v) {
158+
switch ($k) {
159+
case Consul::HTTPAddrEnvName:
160+
$conf['Address'] = $v;
161+
break;
162+
case Consul::HTTPTokenEnvName:
163+
$conf['Token'] = $v;
164+
break;
165+
case Consul::HTTPAuthEnvName:
166+
$conf['HttpAuth'] = $v;
167+
break;
168+
case Consul::HTTPCAFileEnvName:
169+
$conf['CAFile'] = $v;
170+
break;
171+
case Consul::HTTPClientCertEnvName:
172+
$conf['CertFile'] = $v;
173+
break;
174+
case Consul::HTTPClientKeyEnvName:
175+
$conf['KeyFile'] = $v;
176+
break;
177+
case Consul::HTTPSSLEnvName:
178+
if ((bool)$v) {
179+
$conf['Scheme'] = 'https';
180+
}
181+
break;
182+
case Consul::HTTPSSLVerifyEnvName:
183+
if ((bool)$v) {
184+
$conf['InsecureSkipVerify'] = true;
185+
}
186+
break;
187+
}
133188
}
134189

135-
$conf->setHttpClient(new Client());
136-
137190
return $conf;
138191
}
139192

@@ -269,6 +322,54 @@ public function setHttpAuth($HttpAuth) {
269322
));
270323
}
271324

325+
/**
326+
* @return string
327+
*/
328+
public function getCAFile() {
329+
return $this->CAFile;
330+
}
331+
332+
/**
333+
* @param string $CAFile
334+
* @return \DCarbone\PHPConsulAPI\Config
335+
*/
336+
public function setCAFile($CAFile) {
337+
$this->CAFile = $CAFile;
338+
return $this;
339+
}
340+
341+
/**
342+
* @return string
343+
*/
344+
public function getCertFile() {
345+
return $this->CertFile;
346+
}
347+
348+
/**
349+
* @param string $CertFile
350+
* @return \DCarbone\PHPConsulAPI\Config
351+
*/
352+
public function setCertFile($CertFile) {
353+
$this->CertFile = $CertFile;
354+
return $this;
355+
}
356+
357+
/**
358+
* @return string
359+
*/
360+
public function getKeyFile() {
361+
return $this->KeyFile;
362+
}
363+
364+
/**
365+
* @param string $KeyFile
366+
* @return \DCarbone\PHPConsulAPI\Config
367+
*/
368+
public function setKeyFile($KeyFile) {
369+
$this->KeyFile = $KeyFile;
370+
return $this;
371+
}
372+
272373
/**
273374
* @return \GuzzleHttp\ClientInterface
274375
*/
@@ -319,15 +420,42 @@ public function intToMillisecond($in) {
319420
return sprintf('%dms', $ms);
320421
}
321422

423+
/**
424+
* @return array
425+
*/
426+
public function getGuzzleRequestOptions() {
427+
// TODO: Define once?
428+
$opts = [
429+
RequestOptions::HTTP_ERRORS => false,
430+
RequestOptions::DECODE_CONTENT => false,
431+
];
432+
433+
if (!$this->isInsecureSkipVerify()) {
434+
$opts[RequestOptions::VERIFY] = false;
435+
} else if ('' !== ($b = $this->getCAFile())) {
436+
$opts[RequestOptions::VERIFY] = $b;
437+
}
438+
439+
if ('' !== ($c = $this->getCertFile())) {
440+
$opts[RequestOptions::CERT] = $c;
441+
$opts[RequestOptions::SSL_KEY] = $this->getKeyFile();
442+
}
443+
444+
return $opts;
445+
}
446+
322447
/**
323448
* @return array
324449
*/
325450
public static function getEnvironmentConfig() {
326451
return array_filter([
327-
'CONSUL_HTTP_ADDR' => static::_tryGetEnvParam('CONSUL_HTTP_ADDR'),
328-
'CONSUL_HTTP_AUTH' => static::_tryGetEnvParam('CONSUL_HTTP_AUTH'),
329-
'CONSUL_HTTP_SSL' => static::_tryGetEnvParam('CONSUL_HTTP_SSL'),
330-
'CONSUL_HTTP_SSL_VERIFY' => static::_tryGetEnvParam('CONSUL_HTTP_SSL_VERIFY')
452+
Consul::HTTPAddrEnvName => static::_tryGetEnvParam(Consul::HTTPAddrEnvName),
453+
Consul::HTTPAuthEnvName => static::_tryGetEnvParam(Consul::HTTPAuthEnvName),
454+
Consul::HTTPCAFileEnvName => static::_tryGetEnvParam(Consul::HTTPCAFileEnvName),
455+
Consul::HTTPClientCertEnvName => static::_tryGetEnvParam(Consul::HTTPClientCertEnvName),
456+
Consul::HTTPClientKeyEnvName => static::_tryGetEnvParam(Consul::HTTPClientKeyEnvName),
457+
Consul::HTTPSSLEnvName => static::_tryGetEnvParam(Consul::HTTPSSLEnvName),
458+
Consul::HTTPSSLVerifyEnvName => static::_tryGetEnvParam(Consul::HTTPSSLVerifyEnvName),
331459
],
332460
function ($val) {
333461
return null !== $val;
@@ -339,6 +467,10 @@ function ($val) {
339467
* @return string|null
340468
*/
341469
protected static function _tryGetEnvParam($param) {
470+
if (isset($_ENV[$param])) {
471+
return $_ENV[$param];
472+
}
473+
342474
if (false !== ($value = getenv($param))) {
343475
return $value;
344476
}

src/Consul.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ class Consul {
3636
const HTTPAddrEnvName = 'CONSUL_HTTP_ADDR';
3737
const HTTPTokenEnvName = 'CONSUL_HTTP_TOKEN';
3838
const HTTPAuthEnvName = 'CONSUL_HTTP_AUTH';
39+
const HTTPCAFileEnvName = "CONSUL_CACERT";
40+
const HTTPClientCertEnvName = "CONSUL_CLIENT_CERT";
41+
const HTTPClientKeyEnvName = "CONSUL_CLIENT_KEY";
3942
const HTTPSSLEnvName = 'CONSUL_HTTP_SSL';
4043
const HTTPSSLVerifyEnvName = 'CONSUL_HTTP_SSL_VERIFY';
4144

tests/Definition/ConfigDefinitionTest.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,14 @@ class ConfigDefinitionTest extends AbstractDefinitionTestCases
2727
/**
2828
* @inheritDoc
2929
*/
30-
protected function getSubjectClassName()
31-
{
30+
protected function getSubjectClassName() {
3231
return Config::class;
3332
}
33+
34+
/**
35+
* @return object
36+
*/
37+
protected function getEmptyInstance() {
38+
return $this->createMock($this->getSubjectClassName());
39+
}
3440
}

0 commit comments

Comments
 (0)