Skip to content

Commit

Permalink
Adding timeout options both CLI and .cigar.json
Browse files Browse the repository at this point in the history
πŸŽ†πŸŽ†πŸŽ† Happy New Year πŸŽ†πŸŽ†πŸŽ†

This PR adds the timeout options discussed in Brunty#31
Closes / implements Brunty#31

Any values in the CLI are overridden by what ever value is in the `.cigar.json`
  • Loading branch information
WyriHaximus committed Dec 31, 2018
1 parent b8d82fb commit e44ac97
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 20 deletions.
12 changes: 12 additions & 0 deletions .cigar.json.example
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,17 @@
"url": "http://httpbin.org/robots.txt",
"status": 200,
"content-type": "text/plain"
},
{
"url": "http://httpbin.org/delay/3",
"status": 200,
"request-timeout": 1,
"response-timeout": 5
},
{
"url": "http://httpbin.org/drip?duration=3",
"status": 200,
"request-timeout": 1,
"response-timeout": 5
}
]
32 changes: 18 additions & 14 deletions bin/cigar
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use Brunty\Cigar\Outputter;
use Brunty\Cigar\Parser;
use Brunty\Cigar\Result;

$options = getopt('c:ia:u:jh:', ['version', 'help', 'quiet', 'config:', 'insecure', 'auth:', 'url:', 'json', 'header:']);
$options = getopt('c:ia:u:jh:t:ct:', ['version', 'help', 'quiet', 'config:', 'insecure', 'auth:', 'url:', 'json', 'header:', 'timeout:', 'connect-timeout:']);

if (isset($options['help'])) {
$content = <<<HELP
Expand All @@ -27,14 +27,16 @@ if (isset($options['help'])) {
cigar [options]
\033[33mOptions:\033[0m
\033[32m-c file.json, --config=file.json\033[0m Use the specified config file instead of the default .cigar.json file
\033[32m-u URL, --url=URL\033[0m Base URL for checks, e.g. https://example.org/
\033[32m-i, --insecure\033[0m Allow invalid SSL certificates
\033[32m-a, --auth\033[0m Authorization header "\074type\076 \074credentials\076"
\033[32m-h, --header\033[0m Custom header "\074name\076: \074value\076"
\033[32m-j, --json\033[0m Output JSON
\033[32m --quiet\033[0m Do not output any message
\033[32m --version\033[0m Print the version of Cigar
\033[32m-c file.json, --config=file.json\033[0m Use the specified config file instead of the default .cigar.json file
\033[32m-u URL, --url=URL\033[0m Base URL for checks, e.g. https://example.org/
\033[32m-i, --insecure\033[0m Allow invalid SSL certificates
\033[32m-a, --auth\033[0m Authorization header "\074type\076 \074credentials\076"
\033[32m-h, --header\033[0m Custom header "\074name\076: \074value\076"
\033[32m-ct, --connect-timeout=TIMEOUT\033[0m Connect Timeout
\033[32m-t, --timeout=TIMEOUT\033[0m Response Timeout
\033[32m-j, --json\033[0m Output JSON
\033[32m --quiet\033[0m Do not output any message
\033[32m --version\033[0m Print the version of Cigar
Created by Matt Brunt
E: [email protected]
Expand Down Expand Up @@ -78,17 +80,19 @@ if ( ! file_exists($file)) {
exit(1);
}

$secure = ! (isset($options['i']) || isset($options['insecure']));
$authorization = $options['a'] ?? $options['auth'] ?? null;
$headers = (array) ($options['h'] ?? $options['header'] ?? []);
$connectTimeout = $options['ct'] ?? $options['connect-timeout'] ?? null;
$timeout = $options['t'] ?? $options['timeout'] ?? null;

try {
$domains = (new Parser($baseUrl))->parse($file);
$domains = (new Parser($baseUrl, $connectTimeout, $timeout))->parse($file);
} catch (\Throwable $e) {
$outputter->writeErrorLine('Unable to parse .cigar.json file');
exit(1);
}

$secure = ! (isset($options['i']) || isset($options['insecure']));
$authorization = $options['a'] ?? $options['auth'] ?? null;
$headers = (array) ($options['h'] ?? $options['header'] ?? []);

$results = (new AsyncChecker($secure, $authorization, $headers))->check($domains);
$passedResults = array_filter($results, function (Result $result) {
return $result->hasPassed();
Expand Down
16 changes: 16 additions & 0 deletions spec/AsyncCheckerSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,20 @@
expect($results[0]->getStatusCode())->toEqual($expected[0]->getStatusCode());
});
});

context('when timeouts are set', function () {
it('checks a URL that will timeout', function () {
// Need to change for a better setup URL that doesn't default to a potentially unknown site
$domain = new Url('https://httpbin.org/delay/3', 200, null, null, 1, 1);
$domains = [$domain];

$results = (new AsyncChecker())->check($domains);

$expected = [
new Result($domain, 0),
];

expect($results[0]->getStatusCode())->toEqual($expected[0]->getStatusCode());
});
});
});
7 changes: 5 additions & 2 deletions spec/ParserSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@
{
"url": "http://httpbin.org/status/418",
"status": 418,
"content": "teapot"
"content": "teapot",
"content-type": "kitchen/teapot",
"connect-timeout": 1,
"timeout": 2
}
]
',
Expand All @@ -31,7 +34,7 @@
$expected = [
new Url('http://httpbin.org/status/418', 418),
new Url('http://httpbin.org/status/200', 200),
new Url('http://httpbin.org/status/418', 418, 'teapot'),
new Url('http://httpbin.org/status/418', 418, 'teapot', 'kitchen/teapot', 1, 2),
];

expect($results)->toEqual($expected);
Expand Down
7 changes: 7 additions & 0 deletions src/AsyncChecker.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,13 @@ public function check(array $urlsToCheck): array
curl_setopt($channel, CURLOPT_HTTPHEADER, $this->headers);
}

if ($urlToCheck->getConnectTimeout() !== null && $urlToCheck->getConnectTimeout() > 0) {
curl_setopt($channel, CURLOPT_CONNECTTIMEOUT, $urlToCheck->getConnectTimeout());
}
if ($urlToCheck->getTimeout() !== null && $urlToCheck->getTimeout() > 0) {
curl_setopt($channel, CURLOPT_TIMEOUT, $urlToCheck->getTimeout());
}

curl_multi_add_handle($mh, $channel);

$channels[$url] = $channel;
Expand Down
23 changes: 21 additions & 2 deletions src/Parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,21 @@ class Parser
*/
private $baseUrl;

public function __construct(string $baseUrl = null)
/**
* @var null|int
*/
private $connectTimeout;

/**
* @var null|int
*/
private $timeout;

public function __construct(string $baseUrl = null, int $connectTimeout = null, int $timeout = null)
{
$this->baseUrl = rtrim($baseUrl, '/');
$this->connectTimeout = $connectTimeout;
$this->timeout = $timeout;
}

/**
Expand All @@ -31,7 +43,14 @@ public function parse(string $filename): array
return array_map(function($value) {
$url = $this->getUrl($value['url']);

return new Url($url, $value['status'], $value['content'] ?? null, $value['content-type'] ?? null);
return new Url(
$url,
$value['status'],
$value['content'] ?? null,
$value['content-type'] ?? null,
$value['connect-timeout'] ?? $this->connectTimeout,
$value['timeout'] ?? $this->timeout
);
}, $urls);
}

Expand Down
32 changes: 30 additions & 2 deletions src/Url.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,30 @@ class Url
*/
private $contentType;

public function __construct(string $url, int $status, string $content = null, string $contentType = null)
{
/**
* @var null|int
*/
private $connectTimeout;

/**
* @var null|int
*/
private $timeout;

public function __construct(
string $url,
int $status,
string $content = null,
string $contentType = null,
int $connectTimeout = null,
int $timeout = null
) {
$this->url = $url;
$this->status = $status;
$this->content = $content;
$this->contentType = $contentType;
$this->connectTimeout = $connectTimeout;
$this->timeout = $timeout;
}

public function getUrl(): string
Expand All @@ -53,4 +71,14 @@ public function getContentType()
{
return $this->contentType;
}

public function getConnectTimeout()
{
return $this->connectTimeout;
}

public function getTimeout()
{
return $this->timeout;
}
}

0 comments on commit e44ac97

Please sign in to comment.