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 相关文章推荐
为php4加入动态flash文件的生成的支持
Oct 09 PHP
php中获得视频时间总长度的另一种方法
Sep 15 PHP
PHP中使用file_get_contents抓取网页中文乱码问题解决方法
Dec 17 PHP
php实现修改新闻时删除图片的方法
May 12 PHP
PHP使用MPDF类生成PDF的方法
Dec 08 PHP
[原创]PHP实现逐行删除文件右侧空格的方法
Dec 25 PHP
PHP根据树的前序遍历和中序遍历构造树并输出后序遍历的方法
Nov 10 PHP
什么是PHP7中的孤儿进程与僵尸进程
Apr 14 PHP
Yii2框架视图(View)操作及Layout的使用方法分析
May 27 PHP
PHP图像处理 imagestring添加图片水印与文字水印操作示例
Feb 06 PHP
TP5框架实现一次选择多张图片并预览的方法示例
Apr 04 PHP
php框架CI(codeigniter)自动加载与自主创建对象操作实例分析
Jun 06 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实现比较全的数据库操作类
2015/06/18 PHP
php上传大文件设置方法
2016/04/14 PHP
PHP获取input输入框中的值去数据库比较显示出来
2016/11/16 PHP
基于swoole实现多人聊天室
2018/06/14 PHP
PHP实现简单注册登录系统
2020/12/28 PHP
关于 byval 与 byref 的区别分析总结
2007/10/08 Javascript
基于jQuery实现点击同时更改两个iframe的网址
2010/07/01 Javascript
javascript 原型链维护和继承详解
2014/11/26 Javascript
jQuery实现带滚动导航效果的全屏滚动相册实例
2015/06/19 Javascript
Jquery实现顶部弹出框特效
2015/08/08 Javascript
Vue.js实现简单ToDoList 前期准备(一)
2016/12/01 Javascript
Angular2中如何使用ngx-translate进行国际化
2017/05/21 Javascript
vue实现全选、反选功能
2020/11/17 Javascript
JS实现浏览上传文件的代码
2017/08/23 Javascript
nginx配置React静态页面的方法教程
2017/11/03 Javascript
js根据json数据中的某一个属性来给数据分组的方法
2018/10/08 Javascript
使用wxapp-img-loader自定义组件实现微信小程序图片预加载功能
2018/10/18 Javascript
Angular实现svg和png图片下载实现
2019/05/05 Javascript
js实现上传按钮并显示缩略图小轮子
2020/05/04 Javascript
Python中的深拷贝和浅拷贝详解
2015/06/03 Python
python使用SMTP发送qq或sina邮件
2017/10/21 Python
python中返回矩阵的行列方法
2018/04/04 Python
在Python中字典根据多项规则排序的方法
2019/01/21 Python
Python 字符串类型列表转换成真正列表类型过程解析
2019/08/26 Python
python中wheel的用法整理
2020/06/15 Python
使用keras内置的模型进行图片预测实例
2020/06/17 Python
keras实现theano和tensorflow训练的模型相互转换
2020/06/19 Python
Jar包的作用是什么
2014/03/30 面试题
学校卫生检查制度
2014/02/03 职场文书
2014年党员加强作风建设思想汇报
2014/09/15 职场文书
基层党员学习党的群众路线教育实践活动心得体会
2014/11/04 职场文书
个人原因辞职信模板
2015/05/13 职场文书
医院保洁员管理制度
2015/08/05 职场文书
ThinkPHP5和ThinkPHP6的区别
2021/03/31 PHP
如何利用Matlab制作一款真正的拼图小游戏
2021/05/11 Python
python中%格式表达式实例用法
2021/06/18 Python