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 相关文章推荐
人大复印资料处理程序_输入篇
Oct 09 PHP
实现 win2003 下 mysql 数据库每天自动备份
Dec 06 PHP
PHP高级对象构建 工厂模式的使用
Feb 05 PHP
浅析php中如何在有限的内存中读取大文件
Jul 02 PHP
FireFox浏览器使用Javascript上传大文件
Oct 30 PHP
PHP中ob_start函数的使用说明
Nov 11 PHP
php动态变量定义及使用
Jun 10 PHP
PHP的运行机制与原理(底层)
Nov 16 PHP
什么是OneThink oneThink后台添加插件步骤
Apr 13 PHP
php微信开发之自定义菜单实现
Nov 18 PHP
laravel框架创建授权策略实例分析
Nov 22 PHP
一文搞懂PHP中的抽象类和接口
May 25 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/07/30 PHP
mysql alter table命令修改表结构实例详解
2016/09/24 PHP
PHP实现将优酷土豆腾讯视频html地址转换成flash swf地址的方法
2017/08/04 PHP
PHP保存Base64图片base64_decode的问题整理
2019/11/04 PHP
jQuery extend 的简单实例
2013/09/18 Javascript
Javascript学习笔记之数组的遍历和 length 属性
2014/11/23 Javascript
jQuery动态背景图片效果实现方法
2015/07/03 Javascript
用javascript实现自动输出网页文本
2015/07/30 Javascript
jquery实现动静态条形统计图
2015/08/17 Javascript
JS实现IE状态栏文字缩放效果代码
2015/10/24 Javascript
详解JavaScript中的构造器Constructor模式
2016/01/14 Javascript
APP中javascript+css3实现下拉刷新效果
2016/01/27 Javascript
Javascript json object 与string 相互转换的简单实现
2016/09/27 Javascript
关于RequireJS的简单介绍即使用方法
2016/10/20 Javascript
用move.js库实现百叶窗特效
2017/02/08 Javascript
简单的Vue异步组件实例Demo
2017/12/27 Javascript
jQuery动态添加li标签并添加属性和绑定事件方法
2018/02/24 jQuery
layui对工具条进行选择性的显示方法
2019/09/19 Javascript
Node.js API详解之 dgram模块用法实例分析
2020/06/05 Javascript
Python笔记(叁)继续学习
2012/10/24 Python
Python使用logging结合decorator模式实现优化日志输出的方法
2016/04/16 Python
python字典多键值及重复键值的使用方法(详解)
2016/10/31 Python
python函数的5种参数详解
2017/02/24 Python
python机器学习库scikit-learn:SVR的基本应用
2019/06/26 Python
python 数据生成excel导出(xlwt,wlsxwrite)代码实例
2019/08/23 Python
python实现的Iou与Giou代码
2020/01/18 Python
pandas数据选取:df[] df.loc[] df.iloc[] df.ix[] df.at[] df.iat[]
2020/04/24 Python
英国电动工具购买网站:Anglia Tool Centre
2017/04/25 全球购物
高中生活自我鉴定
2014/01/18 职场文书
关于奉献的演讲稿
2014/05/21 职场文书
学习考察心得体会
2014/09/04 职场文书
个人股份转让协议书范本
2014/10/26 职场文书
2015年度公共机构节能工作总结
2015/05/26 职场文书
革命电影观后感
2015/06/18 职场文书
MyBatis在注解上使用动态SQL方式(@select使用if)
2022/07/07 Java/Android
MySQL添加索引特点及优化问题
2022/07/23 MySQL