To accomplish this, I think we need to simply test for the Timeout we're looking for. So I see the following scenarios:
- Timeout connecting to the URL (Connection Time Out - Host down)
- Timeout performing the operation (Operation Time Out)
- Timeout due to Slow connection (Low Speed Time)
We can check for the first timeout using other methods. So lets do that:
<?php
$site="http://www.google.com";
$content = file_get_contents($site);
if($content === false){
// Host dead, handle error here...
}
?>
Reference: How can I handle the warning of file_get_contents() function in PHP?
At this point, we know that we should not get a connection timeout. We can proceed with the curl execution and know that it will be an operation timeout or speed.
<?php
function curl_run($opts){
$content = file_get_contents($opts[CURLOPT_URL]);
if($content === false){
return false;
} else {
$resp = array();
$time_start = microtime(true);
$ch = curl_init();
curl_setopt_array($ch, $opts);
$resp['result'] = curl_exec($ch);
$time_end = microtime(true);
$resp['info'] = curl_getinfo($ch);
if(curl_errno($ch)){
$resp['error'] = curl_error($ch);
}
curl_close($ch);
$resp['time'] = $time_end - $time_start; // Time it took
return $resp;
}
}
$url = isset($_GET['url'])?$_GET['url']:"http://www.google.com/";
$options = array(
CURLOPT_URL => $url,
CURLOPT_HEADER => true,
CURLOPT_TIMEOUT_MS => 1000,
CURLOPT_CONNECTTIMEOUT_MS => 10,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_VERBOSE => 1
);
$results = curl_run($options);
if($results){
echo "<h2>Options</h2>\r\n";
echo "<pre>";
foreach($options as $k => $v){
echo "$k: $v\r\n";
}
echo "</pre>";
echo "<h2>Info</h2>\r\n";
echo "<pre>";
foreach($results['info'] as $k => $v){
echo "$k: $v\r\n";
}
echo "time: {$results['time']}\r\n";
echo "</pre>\r\n";
if(isset($results['error'])){
echo "<h2>Error</h2>\r\n";
echo "<pre>{$results['error']}</pre>\r\n";
}
echo "<h2>Response</h2>\r\n";
echo "<pre>" . htmlentities($results['result']) . "</pre>";
}
?>
We should be able to look at all of that and determine if the time it took to execute the operation was then close to one of our Timeout settings. Otherwise we would also have lots of data under info
too. If it returns false, we know the host was unreachable.
Did further testing, and you can see them here: http://www.yrmailfrom.me/projects/php/curl_test1.php?url=http://www.apple.com/
I found that Apple.com was taking 14 ms, so it became a good test.
Example output:
Options
10002: http://www.apple.com/
42: 1
155: 1000
156: 10
19913: 1
41: 1
Info
url: http://www.apple.com/
content_type:
http_code: 0
header_size: 0
request_size: 0
filetime: -1
ssl_verify_result: 0
redirect_count: 0
total_time: 0.014634
namelookup_time: 0.004297
connect_time: 0
pretransfer_time: 0
size_upload: 0
size_download: 0
speed_download: 0
speed_upload: 0
download_content_length: -1
upload_content_length: -1
starttransfer_time: 0
redirect_time: 0
redirect_url:
primary_ip:
certinfo: Array
primary_port: 0
local_ip:
local_port: 0
time: 0.014760017395
Error
Connection timed out after 14 milliseconds
Response