PHP實(shí)現(xiàn)的帶超時(shí)功能get_headers函數(shù)

字號(hào):

這篇文章主要介紹了PHP實(shí)現(xiàn)的帶超時(shí)功能的get_headers函數(shù),本文直接給出實(shí)現(xiàn)代碼,需要的朋友可以參考下
    代碼比較多,但是比較簡(jiǎn)單,一眼就看穿的,so,文字盡量少寫了。
    因?yàn)楸娝苤木W(wǎng)絡(luò)原因,gavatar也開始越來越慢,寫了一個(gè)小東西來解決這個(gè)問題,過程中遇到了get_headers這個(gè)函數(shù),甚是憂傷,記錄下來,以免后來人踩坑。
    更新記錄,函數(shù)稍微改了一下,返回值基本和之前序列化后的結(jié)果一致,暫時(shí)沒考慮支持子項(xiàng)也支持?jǐn)?shù)組等(考慮細(xì)節(jié)性能,還想把沒用的http頭砍掉….)
    需求很簡(jiǎn)單:獲取圖片的head信息。
    調(diào)試程序的時(shí)候發(fā)現(xiàn)這個(gè)函數(shù)的調(diào)用很緩慢,即使綁定ip,有時(shí)候都能蹦到20多秒。
    尋思這個(gè)事情還是該加個(gè)超時(shí)吧,但是看官方文檔,給出的導(dǎo)出函數(shù)接口如下:
    代碼如下:
    array get_headers(string$url[,int$format=0])
    你沒有看錯(cuò),這個(gè)東西沒有超時(shí)接口…
    上github翻看源碼,期望可以用他的底層實(shí)現(xiàn)來重新實(shí)現(xiàn)一套:
    地址
    代碼如下:
    /* {{{ proto array get_headers(string url[, int format])
    fetches all the headers sent by the server in response to a HTTP request */
    PHP_FUNCTION(get_headers)
    {
    char*url;
    size_t url_len;
    php_stream_context*context;
    php_stream*stream;
    zval*prev_val,*hdr=NULL,*h;
    HashTable*hashT;
    zend_long format=0;
    if(zend_parse_parameters(ZEND_NUM_ARGS()TSRMLS_CC,"s|l",&url,&url_len,&format)==FAILURE){
    return;
    }
    /** 省略其他一堆... **/
    }
    /* }}} */
    但是很不幸的是,zend_parse_parameters 和 ZEND_NUM_ARGS也都沒有PHP版的導(dǎo)出函數(shù)。
    于是造輪子開始:
    復(fù)制代碼 代碼如下:
    functionget_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){
    case2:
    returnarray($data[0]=>$data[1]);
    break;
    case1:
    return$data;
    break;
    default:
    break;
    }
    }
    },$data));
    sort($data);
    foreach($dataas$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;
    }
    對(duì)比最后結(jié)果:
    原版又是蠻長(zhǎng)的等待,不知道校驗(yàn)啥去了(沒繼續(xù)追代碼了,有興趣的童鞋可以去跟下玩):
    代碼如下:
    Array
    (
    [0]=>HTTP/1.0302Found
    [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,12Dec201415:35:40GMT
    [1]=>Fri,12Dec201415:35:43GMT
    )
    [Expires]=>Fri,12Dec201415:40:40GMT
    [Last-Modified]=>Wed,11Jan198408:00:00GMT
    [Link]=>
    [Location]=>http://i2.wp.com/[省略...]
    [Server]=>Array
    (
    [0]=>ECS(oxr/838B)
    [1]=>nginx
    )
    [Source-Age]=>85
    [Via]=>1.1varnish
    [X-Cache]=>302-HIT
    [X-Varnish]=>14702550881470006304
    [Content-Length]=>0
    [Connection]=>Array
    (
    [0]=>close
    [1]=>close
    )
    [1]=>HTTP/1.1504Gateway Timeout
    )
    輪子版返回(瞬間返回,兩者內(nèi)容略有不同,你仔細(xì)看就能發(fā)現(xiàn)一些有趣的地方了):
    代碼如下:
    Array
    (
    [0]=>HTTP/1.1302Found
    [Accept-Ranges]=>bytes
    [Via]=>1.1varnish
    [Cache-Control]=>max-age=300
    [Server]=>ECS(oxr/838B)
    [Content-Type]=>text/html;charset=utf-8
    [X-Varnish]=>14702550881470006304
    [Date]=>Fri,12Dec201420:31:02GMT
    [Location]=>http://i2.wp.com/[省略...]
    [Expires]=>Fri,12Dec201420:36:02GMT
    [Source-Age]=>85
    [Last-Modified]=>Wed,11Jan198408:00:00GMT
    [X-Cache]=>302-HIT
    [Link]=>
    [Content-Length]=>0
    )