因網路環境限制,Gravatar 等外部資源存取愈發緩慢。開發過程中使用 get_headers 取得圖片 Head 資訊,卻發現該函數呼叫極其緩慢,即使綁定 IP 仍可能耗時 20 秒以上。官方文檔顯示 get_headers(string $url[, int $format = 0]) 並無超時參數,翻閱 PHP 原始碼(url.c)發現底層依賴 zend_parse_parameters 等內部 API,無法直接在使用者層複用。
既然原生函數不支援超時,便以 cURL 重寫一個 get_url_headers 函數:
function get_url_headers($url, $timeout = 10)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
$data = curl_exec($ch);
$data = preg_split('/\n/', $data);
$data = array_filter(array_map(function($data){
$data = trim($data);
if($data){
$data = preg_split('/:\s/', trim($data), 2);
$length = count($data);
switch($length){
case 2:
return array($data[0] => $data[1]);
break;
case 1:
return $data;
break;
default:
break;
}
}
}, $data));
sort($data);
foreach($data as $key => $value){
$itemKey = array_keys($value)[0];
if(is_int($itemKey)){
$data[$key] = $value[$itemKey];
}elseif(is_string($itemKey)){
$data[$itemKey] = $value[$itemKey];
unset($data[$key]);
}
}
return $data;
}
Array
(
[0] => HTTP/1.0 302 Found
[Accept-Ranges] => bytes
[Cache-Control] => max-age=300
[Content-Type] => Array
(
[0] => text/html;charset=utf-8
[1] => text/html;charset=utf-8
)
[Date] => Array
(
[0] => Fri, 12 Dec 2014 15:35:40 GMT
[1] => Fri, 12 Dec 2014 15:35:43 GMT
)
[Expires] => Fri, 12 Dec 2014 15:40:40 GMT
[Last-Modified] => Wed, 11 Jan 1984 08:00:00 GMT
[Link] => <https://www.gravatar.com/avatar/...>; rel="canonical"
[Location] => https://i2.wp.com/...
[Server] => Array
(
[0] => ECS(oxr/838B)
[1] => nginx
)
[Source-Age] => 85
[Via] => 1.1 varnish
[X-Cache] => 302-HIT
[X-Varnish] => 14702550881470006304
[Content-Length] => 0
[Connection] => Array
(
[0] => close
[1] => close
)
[1] => HTTP/1.1 504 Gateway Timeout
)
Array
(
[0] => HTTP/1.1 302 Found
[Accept-Ranges] => bytes
[Via] => 1.1 varnish
[Cache-Control] => max-age=300
[Server] => ECS(oxr/838B)
[Content-Type] => text/html;charset=utf-8
[X-Varnish] => 14702550881470006304
[Date] => Fri, 12 Dec 2014 20:31:02 GMT
[Location] => https://i2.wp.com/...
[Expires] => Fri, 12 Dec 2014 20:36:02 GMT
[Source-Age] => 85
[Last-Modified] => Wed, 11 Jan 1984 08:00:00 GMT
[X-Cache] => 302-HIT
[Link] => <https://www.gravatar.com/avatar/...>; rel="canonical"
[Content-Length] => 0
)
自製函數不僅解決超時問題,回傳結構也更扁平、易用。兩者內容略有差異(如重複 Header 的處理),可根據實際需求調整解析邏輯。