/
ExternalURLCheck.php
137 lines (122 loc) · 3.39 KB
/
ExternalURLCheck.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
<?php
namespace SilverStripe\EnvironmentCheck\Checks;
use SilverStripe\EnvironmentCheck\EnvironmentCheck;
/**
* Checks that one or more URLs are reachable via HTTP.
* Note that the HTTP connectivity can just be verified from the server to the remote URL,
* it can still fail if the URL in question is requested by the client, e.g. through an iframe.
*
* Requires curl to present, so ensure to check it before with the following:
* <code>
* EnvironmentCheckSuite::register(
* 'check',
* 'HasFunctionCheck("curl_init")',
* "Does PHP have CURL support?"
* );
* </code>
*/
class ExternalURLCheck implements EnvironmentCheck
{
/**
* @var array
*/
protected $urls = [];
/**
* @var Int Timeout in seconds.
*/
protected $timeout;
/**
* @param string $urls Space-separated list of absolute URLs.
* @param int $timeout
*/
public function __construct($urls, $timeout = 15)
{
if ($urls) {
$this->urls = explode(' ', $urls ?? '');
}
$this->timeout = $timeout;
}
/**
* {@inheritDoc}
*
* @return array
*/
public function check()
{
$urls = $this->getURLs();
$chs = [];
foreach ($urls as $url) {
$ch = curl_init();
$chs[] = $ch;
curl_setopt_array($ch, $this->getCurlOpts($url) ?? []);
}
// Parallel execution for faster performance
$mh = curl_multi_init();
foreach ($chs as $ch) {
curl_multi_add_handle($mh, $ch);
}
$active = null;
// Execute the handles
do {
$mrc = curl_multi_exec($mh, $active);
curl_multi_select($mh);
} while ($active > 0);
while ($active && $mrc == CURLM_OK) {
if (curl_multi_select($mh) != -1) {
do {
$mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
}
}
$hasError = false;
$msgs = [];
foreach ($chs as $ch) {
$url = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch) || $code >= 400) {
$hasError = true;
$msgs[] = sprintf(
'Error retrieving "%s": %s (Code: %s)',
$url,
curl_error($ch),
$code
);
} else {
$msgs[] = sprintf(
'Success retrieving "%s" (Code: %s)',
$url,
$code
);
}
}
// Close the handles
foreach ($chs as $ch) {
curl_multi_remove_handle($mh, $ch);
}
curl_multi_close($mh);
if ($hasError) {
return [EnvironmentCheck::ERROR, implode(', ', $msgs)];
}
return [EnvironmentCheck::OK, implode(', ', $msgs)];
}
/**
* @return array
*/
protected function getCurlOpts($url)
{
return [
CURLOPT_URL => $url,
CURLOPT_HEADER => 0,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_FAILONERROR => 1,
CURLOPT_TIMEOUT => $this->timeout,
];
}
/**
* @return array
*/
protected function getURLs()
{
return $this->urls;
}
}