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 相关文章推荐
六酷社区论坛HOME页清新格调免费版 下载
Mar 07 PHP
PHP伪静态页面函数附使用方法
Jun 20 PHP
Linux编译升级php的详细方法
Nov 04 PHP
ThinkPHP中的关联模型注意点
Jun 16 PHP
php.ini save_handler 修改不生效的解决办法
Jul 22 PHP
ThinkPHP权限认证Auth实例详解
Jul 22 PHP
支持中文的PHP按字符串长度分割成数组代码
May 17 PHP
PHP的APC模块实现上传进度条
Oct 27 PHP
PHP可变变量学习小结
Nov 29 PHP
简介PHP的Yii框架中缓存的一些高级用法
Mar 29 PHP
Thinkphp实现短信验证注册功能
Oct 18 PHP
tp5框架使用composer实现日志记录功能示例
Jan 10 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初学者头疼十四条问题大总结
2008/11/12 PHP
ThinkPHP的常用配置选项汇总
2016/03/24 PHP
CI框架支持$_GET的两种实现方法
2016/05/18 PHP
PHP中“=&gt;
2019/03/01 PHP
PHP 对象继承原理与简单用法示例
2020/04/21 PHP
JQuery实现表格动态增加行并对新行添加事件
2014/07/30 Javascript
jQuery实现的五子棋游戏实例
2015/06/13 Javascript
JavaScript 定时器 SetTimeout之定时刷新窗口和关闭窗口(代码超简单)
2016/02/26 Javascript
JS中多步骤多分步的StepJump组件实例详解
2016/04/01 Javascript
NodeJS与HTML5相结合实现拖拽多个文件上传到服务器的实现方法
2016/07/26 NodeJs
Bootstrap轮播图的使用和理解4
2016/12/14 Javascript
实例详解display:none与visible:hidden的区别
2017/03/30 Javascript
详解react-router如何实现按需加载
2017/06/15 Javascript
vue2.0 路由不显示router-view的解决方法
2018/03/06 Javascript
vue实现固定位置显示功能
2019/05/30 Javascript
ionic3双击返回退出应用的方法
2019/09/17 Javascript
js实现踩五彩块游戏
2020/02/08 Javascript
python命令行参数sys.argv使用示例
2014/01/28 Python
python pandas中DataFrame类型数据操作函数的方法
2018/04/08 Python
在PyCharm中遇到pip安装 失败问题及解决方案(pip失效时的解决方案)
2020/03/10 Python
CSS3实现银灰色动画效果的导航菜单代码
2015/09/01 HTML / CSS
台湾深度自由行旅游平台:Tripbaa趣吧
2017/10/10 全球购物
印度化妆品购物网站:Nykaa
2018/07/22 全球购物
美国最大的在线水培用品商店:GrowersHouse.com
2018/08/14 全球购物
测试时代收集的软件测试面试题
2013/09/25 面试题
JSF界面控制层技术
2013/06/17 面试题
开展党的群众路线教育实践活动方案
2014/02/05 职场文书
员工保密承诺书
2014/05/28 职场文书
教师专业自荐信
2014/05/31 职场文书
行政求职信
2014/07/04 职场文书
纪检监察立案决定书
2015/06/24 职场文书
青年人初次创业的“五不要”
2019/08/23 职场文书
Pytorch 如何实现常用正则化
2021/05/27 Python
CSS文本阴影 text-shadow 悬停效果详解
2022/05/25 HTML / CSS
win sever 2022如何占用操作主机角色
2022/06/25 Servers
Python 第三方库 openpyxl 的安装过程
2022/12/24 Python