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 相关文章推荐
PHP 加密与解密的斗争
Apr 17 PHP
Linux环境下搭建php开发环境的操作步骤
Jun 17 PHP
如何使用“PHP” 彩蛋进行敏感信息获取
Aug 07 PHP
php ZipArchive压缩函数详解实例
Nov 06 PHP
ThinkPHP中的常用查询语言汇总
Aug 22 PHP
PHP模块memcached使用指南
Dec 08 PHP
详解php魔术方法(Magic methods)的使用方法
Feb 14 PHP
浅谈thinkphp5 instance 的简单实现
Jul 30 PHP
利用PHP访问MySql数据库的逻辑操作以及增删改查的实例讲解
Aug 30 PHP
PHP观察者模式示例【Laravel框架中有用到】
Jun 15 PHP
Yii2语言国际化的配置教程
Aug 19 PHP
Yii Framework框架开发微信公众平台示例
Apr 26 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 SPL使用方法和他的威力
2013/11/12 PHP
php_imagick实现图片剪切、旋转、锐化、减色或增加特效的方法
2014/12/15 PHP
PHP Imagick完美实现图片裁切、生成缩略图、添加水印
2016/02/22 PHP
PHP递归实现快速排序的方法示例
2017/12/18 PHP
PHP图像处理技术实例总结【绘图、水印、验证码、图像压缩】
2018/12/08 PHP
PHP simplexml_import_dom()函数讲解
2019/02/03 PHP
php数值计算num类简单操作示例
2020/05/15 PHP
js jquery验证银行卡号信息正则学习
2013/01/21 Javascript
jquery与js函数冲突的两种解决方法
2013/09/09 Javascript
jQuery如何封装输入框插件
2016/08/19 Javascript
js上传图片预览的实现方法
2017/05/09 Javascript
puppeteer实现html截图的示例代码
2019/01/10 Javascript
简单了解Ajax表单序列化的实现方法
2019/06/14 Javascript
vue实现输入框的模糊查询的示例代码(节流函数的应用场景)
2019/09/01 Javascript
javascript实现随机抽奖功能
2020/12/30 Javascript
vue仿携程轮播图效果(滑动轮播,下方高度自适应)
2021/02/11 Vue.js
Python 字符串操作方法大全
2014/03/11 Python
用python + hadoop streaming 分布式编程(一) -- 原理介绍,样例程序与本地调试
2014/07/14 Python
python处理csv数据的方法
2015/03/11 Python
使用Python编写简单的画图板程序的示例教程
2015/12/08 Python
基于Python和Scikit-Learn的机器学习探索
2017/10/16 Python
python实现QQ空间自动点赞功能
2019/04/09 Python
Python3.5内置模块之shelve模块、xml模块、configparser模块、hashlib、hmac模块用法分析
2019/04/27 Python
python pytest进阶之conftest.py详解
2019/06/27 Python
python读取.mat文件的数据及实例代码
2019/07/12 Python
python随机数分布random均匀分布实例
2019/11/27 Python
matplotlib实现显示伪彩色图像及色度条
2019/12/07 Python
Python用户自定义异常的实现
2020/12/25 Python
利用HTML5 Canvas制作一个简单的打飞机游戏
2015/05/11 HTML / CSS
美国在线鲜花速递:ProFlowers
2017/01/05 全球购物
德国化妆品和天然化妆品网上商店:kosmetikfuchs.de
2017/06/09 全球购物
2014幼儿园教师个人工作总结
2014/11/08 职场文书
工作检讨书范文
2015/01/23 职场文书
幼儿园辞职信范文
2015/02/27 职场文书
2016党员党课心得体会
2016/01/07 职场文书
Python 正则模块详情
2021/11/02 Python