Skip to content

Commit a6bfc40

Browse files
committed
Merge branch 'issue139/heartbeat-ssl-endpoint'
2 parents d8800ae + 98fef0a commit a6bfc40

File tree

3 files changed

+74
-19
lines changed

3 files changed

+74
-19
lines changed

src/Vies/HeartBeat.php

Lines changed: 68 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
*/
2929
class HeartBeat
3030
{
31+
private const DEFAULT_TIMEOUT = 10;
32+
3133
/**
3234
* @var string The host you want to verify
3335
*/
@@ -57,7 +59,7 @@ class HeartBeat
5759
* @param int $port
5860
* @param int $timeout
5961
*/
60-
public function __construct(?string $host = null, int $port = 80, int $timeout = 10)
62+
public function __construct(?string $host = null, int $port = Vies::VIES_PORT, int $timeout = self::DEFAULT_TIMEOUT)
6163
{
6264
if (null !== $host) {
6365
$this->setHost($host);
@@ -150,23 +152,35 @@ public function isAlive(): bool
150152
*/
151153
private function reachOut(): bool
152154
{
153-
$errno = 0;
154-
$error = '';
155-
$hostname = $this->getHost();
156-
$portNumber = $this->getPort();
157-
$timeToLive = $this->getTimeout();
158155
try {
159-
if (false === ($handle = \fsockopen('tcp://' . $hostname, $portNumber, $errno, $error, $timeToLive))) {
160-
return false;
161-
}
162-
} catch (\Exception $exception) {
156+
$data = $this->getSecuredResponse();
157+
} catch (\RuntimeException $runtimeException) {
163158
return false;
164159
}
160+
return (
161+
(0 === strcmp('HTTP/1.1 200 OK', $data[0])) ||
162+
(0 === strcmp('HTTP/1.1 307 Temporary Redirect', $data[0]))
163+
);
164+
}
165+
166+
/**
167+
* This method will make a simple request inside a stream
168+
* resource to retrieve its contents. Useful inside secured
169+
* streams.
170+
*
171+
* @param resource $handle
172+
* @return array
173+
*/
174+
private function readContents($handle): array
175+
{
176+
if (! is_resource($handle)) {
177+
throw new \InvalidArgumentException('Expecting a resource to be provided');
178+
}
165179
$response = '';
166-
$uri = sprintf('%s://%s/', Vies::VIES_PROTO, Vies::VIES_DOMAIN);
180+
$uri = sprintf('%s://%s/', Vies::VIES_PROTO, $this->host);
167181
$stream = [
168182
'GET ' . $uri . ' HTTP/1.0',
169-
'Host: ' . Vies::VIES_DOMAIN,
183+
'Host: ' . $this->host,
170184
'Connection: close',
171185
];
172186
fwrite($handle, implode("\r\n", $stream) . "\r\n\r\n");
@@ -176,9 +190,48 @@ private function reachOut(): bool
176190
fclose($handle);
177191
$response = str_replace("\r\n", PHP_EOL, $response);
178192
$data = explode(PHP_EOL, $response);
179-
return (
180-
(0 === strcmp('HTTP/1.1 200 OK', $data[0])) ||
181-
(0 === strcmp('HTTP/1.1 307 Temporary Redirect', $data[0]))
193+
return $data;
194+
}
195+
196+
/**
197+
* Will make a secured request over SSL/TLS where this
198+
* method will first create a secured stream before
199+
* making the request.
200+
*
201+
* @return array
202+
* @throws \RuntimeException
203+
* @see https://bytephunk.wordpress.com/2017/11/27/ssl-tls-stream-sockets-in-php-7/
204+
*/
205+
private function getSecuredResponse(): array
206+
{
207+
$streamOptions = [
208+
'ssl' => [
209+
'verify_peer' => true,
210+
'verify_peer_name' => true,
211+
'allow_self_signed' => false,
212+
],
213+
];
214+
$streamContext = stream_context_create($streamOptions);
215+
$socketAddress = sprintf(
216+
'tls://%s:%d',
217+
$this->host,
218+
$this->port
219+
);
220+
$error = null;
221+
$errno = null;
222+
$stream = stream_socket_client(
223+
$socketAddress,
224+
$errno,
225+
$error,
226+
self::DEFAULT_TIMEOUT,
227+
STREAM_CLIENT_CONNECT,
228+
$streamContext
182229
);
230+
231+
if (! $stream) {
232+
throw new \RuntimeException('Can not create socket stream: ' . $error);
233+
}
234+
235+
return $this->readContents($stream);
183236
}
184237
}

src/Vies/Vies.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@
4646
*/
4747
class Vies
4848
{
49-
const VIES_PROTO = 'http';
49+
const VIES_PROTO = 'https';
5050
const VIES_DOMAIN = 'ec.europa.eu';
51-
const VIES_PORT = 80;
51+
const VIES_PORT = 443;
5252
const VIES_WSDL = '/taxation_customs/vies/checkVatService.wsdl';
5353
const VIES_TEST_WSDL = '/taxation_customs/vies/checkVatTestService.wsdl';
5454
const VIES_EU_COUNTRY_TOTAL = 29;

tests/Vies/HeartBeatTest.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public function testDefaultPortIsHttp()
3232
{
3333
$hb = new HeartBeat();
3434
$port = $hb->getPort();
35-
$this->assertSame(80, $port);
35+
$this->assertSame(443, $port);
3636
}
3737

3838
/**
@@ -113,14 +113,16 @@ public function socketProvider(): array
113113
{
114114
return [
115115
'Non-existing socket on localhost' => ['127.0.0.1', -1, 10, false],
116-
'Socket 80 on ec.europe.eu' => [Vies::VIES_DOMAIN, Vies::VIES_PORT, 10, true],
116+
'Socket 443 on ec.europe.eu' => [Vies::VIES_DOMAIN, Vies::VIES_PORT, 10, true],
117117
];
118118
}
119119

120120
/**
121121
* @dataProvider socketProvider
122122
* @covers ::isAlive
123123
* @covers ::reachOut
124+
* @covers ::getSecuredResponse
125+
* @covers ::readContents
124126
*/
125127
public function testIsAliveUsingSockets($host, $port, $timeout, $expectedResult)
126128
{

0 commit comments

Comments
 (0)