首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 實作帶超時功能的 get_headers 函數:以 cURL 替代原生函數

     編輯:PHP 相關知識

緣起

因網路環境限制,Gravatar 等外部資源存取愈發緩慢。開發過程中使用 get_headers 取得圖片 Head 資訊,卻發現該函數呼叫極其緩慢,即使綁定 IP 仍可能耗時 20 秒以上。官方文檔顯示 get_headers(string $url[, int $format = 0]) 並無超時參數,翻閱 PHP 原始碼(url.c)發現底層依賴 zend_parse_parameters 等內部 API,無法直接在使用者層複用。

自製替代方案:以 cURL 實現

既然原生函數不支援超時,便以 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;
}

結果對比

原生 get_headers(耗時長、結果冗長)

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 的處理),可根據實際需求調整解析邏輯。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved