PHP实现的带超时功能get_headers函数


Posted in PHP onFebruary 10, 2015

代码比较多,但是比较简单,一眼就看穿的,so,文字尽量少写了。
因为众所周知的网络原因,gavatar也开始越来越慢,写了一个小东西来解决这个问题,过程中遇到了get_headers这个函数,甚是忧伤,记录下来,以免后来人踩坑。
更新记录,函数稍微改了一下,返回值基本和之前序列化后的结果一致,暂时没考虑支持子项也支持数组等(考虑细节性能,还想把没用的http头砍掉….)
需求很简单:获取图片的head信息。
调试程序的时候发现这个函数的调用很缓慢,即使绑定ip,有时候都能蹦到20多秒。
寻思这个事情还是该加个超时吧,但是看官方文档,给出的导出函数接口如下:

array get_headers(string$url[,int$format=0])

你没有看错,这个东西没有超时接口…
上github翻看源码,期望可以用他的底层实现来重新实现一套:
地址 https://github.com/php/php-src/blob/88ca46d92bc1c426e7c7f7313f0fd2b7dcc33cf6/ext/standard/url.c#L710
/* {{{ 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版的导出函数。
于是造轮子开始:

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;

}

对比最后结果:
原版又是蛮长的等待,不知道校验啥去了(没继续追代码了,有兴趣的童鞋可以去跟下玩):

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]=><http://www.gravatar.com/avatar/[省略...]?s=42&d=http%3A%2F%2F[省略...]&r=G>; rel="canonical"

    [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

)

轮子版返回(瞬间返回,两者内容略有不同,你仔细看就能发现一些有趣的地方了):

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]=><http://www.gravatar.com/avatar/[省略...]?s=42&d=http%3A%2F%2F[省略...]&r=G>; rel="canonical"

    [Content-Length]=>0

)
PHP 相关文章推荐
用cookies来跟踪识别用户
Oct 09 PHP
PHP 和 MySQL 开发的 8 个技巧
Jan 02 PHP
php实现用户在线时间统计详解
Oct 08 PHP
php数组函数序列之rsort() - 对数组的元素值进行降序排序
Nov 02 PHP
php二维数组排序与默认自然排序的方法介绍
Apr 27 PHP
php中用加号与用array_merge合并数组的区别深入分析
Jun 03 PHP
PHP中怎样防止SQL注入分析
Oct 23 PHP
php的GD库imagettftext函数解决中文乱码问题
Jan 24 PHP
php实现将任意进制数转换成10进制的方法
Apr 17 PHP
CI框架出现mysql数据库连接资源无法释放的解决方法
May 17 PHP
PHP实现的网站目录扫描索引工具
Sep 08 PHP
PHP将URL转换成短网址的算法分享
Sep 13 PHP
Laravel框架中实现使用阿里云ACE缓存服务
Feb 10 #PHP
Laravel中扩展Memcached缓存驱动实现使用阿里云OCS缓存
Feb 10 #PHP
PHP框架Laravel的小技巧两则
Feb 10 #PHP
Laravel模板引擎Blade中section的一些标签的区别介绍
Feb 10 #PHP
Laravel 5.0 发布 新版本特性详解
Feb 10 #PHP
PHP转盘抽奖接口实例
Feb 09 #PHP
PHP积分兑换接口实例
Feb 09 #PHP
You might like
鸡肋的PHP单例模式应用详解
2013/06/03 PHP
Java和PHP在Web开发方面对比分析
2015/03/01 PHP
PHP实现过滤各种HTML标签
2015/05/17 PHP
Yii2 输出xml格式数据的方法
2016/05/03 PHP
PHP实现的曲线统计图表示例
2016/11/10 PHP
PHP给源代码加密的几种方法汇总(推荐)
2018/02/06 PHP
javascript 函数速查表
2010/02/07 Javascript
基于jQuery的自动完成插件
2011/02/03 Javascript
把jQuery的类、插件封装成seajs的模块的方法
2014/03/12 Javascript
JavaScript字符串对象的concat方法实例(用于连接两个或多个字符串)
2014/10/16 Javascript
Jquery 实现grid绑定模板
2015/01/28 Javascript
RequireJS入门一之实现第一个例子
2015/09/30 Javascript
js输出数据精确到小数点后n位代码
2016/07/02 Javascript
js实现横向拖拽导航条功能
2017/02/17 Javascript
浅谈原生JS实现jQuery的animate()动画示例
2017/03/08 Javascript
vue中路由参数传递可能会遇到的坑
2017/12/07 Javascript
react中实现搜索结果中关键词高亮显示
2018/07/31 Javascript
微信小程序使用 vant Dialog组件的正确方式
2020/02/21 Javascript
vue项目实现设置根据路由高亮对应的菜单项操作
2020/08/06 Javascript
Python爬虫包BeautifulSoup实例(三)
2018/06/17 Python
PYQT5开启多个线程和窗口,多线程与多窗口的交互实例
2019/12/13 Python
Python测试框架:pytest学习笔记
2020/10/20 Python
Ancheer官方户外和运动商店:销售电动自行车
2019/08/07 全球购物
世界上最伟大的马产品:Equiderma
2020/01/07 全球购物
应聘教师自荐信
2013/10/12 职场文书
蔬菜基地的创业计划书
2014/01/06 职场文书
2015元旦家电促销活动策划方案
2014/12/09 职场文书
孝老爱亲事迹材料
2014/12/24 职场文书
街道党风廉政建设调研报告
2015/01/01 职场文书
给上级领导的感谢信
2015/01/22 职场文书
仓管员岗位职责
2015/02/03 职场文书
神龙架导游词
2015/02/11 职场文书
立案决定书范文
2015/06/24 职场文书
运输公司工作总结
2015/08/11 职场文书
创业分两种人:那么哪些适合创业?,哪些适合不适合创业呢?
2019/08/23 职场文书
导游词之清晏园
2019/11/22 职场文书