MarkR wrote:Well, I don't. fopen() is the right way to go.
If you believe downloading a complete file is the right way to go just to check it exists, you are in the wrong line of work. What if the file was 100 megabytes?
MarkR wrote:, there's no way in the stock HTTP implementation to set the timeout separately at different stages of the request - such as connect, waiting for headers or waiting for the content etc.
If the server accepts the connection but hangs indefinitely after doing so, PHP doesn't appear to have a timeout at this stage at all. This is obviously not helpful for an automated web checker, spider, robot etc.
stream_set_timeout(); can be altered before any step.
Here's a function that will get the status code without downloading the contents:
function http_file_status($url, $followRedirects = true)
{
$url_parsed = parse_url($url);
if (!@$url_parsed['scheme']) $url_parsed = parse_url('http://'.$url);
extract($url_parsed);
if(!@$port) $port = 80;
if(!@$path) $path = '/';
if(@$query) $path .= '?'.$query;
$out = "HEAD $path HTTP/1.1\r\n";
$out .= "Host: $host\r\n";
$out .= "Connection: Close\r\n\r\n";
if(!$fp = @fsockopen($host, $port, $es, $en, 5)){
return false;
}
fwrite($fp, $out);
while (!feof($fp)) {
$s = fgets($fp, 128);
if(($followRedirects) && (preg_match('/^Location:/i', $s) != false)){
fclose($fp);
return http_file_status(trim(preg_replace("/Location:/i", "", $s)));
}
if(preg_match('@HTTP[/]1[.][01x][\s]{1,}([1-5][01][0-9])[\s].*$@', $s, $matches))
{
$status = $matches[1];
}
}
fclose($fp);
if(!empty($status))
{
return $status;
}
return false;
}