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
虚拟主机中对PHP的特殊设置
Oct 09 PHP
PHP 输出简单动态WAP页面
Jun 09 PHP
PHP采集相关教程之一 CURL函数库
Feb 15 PHP
PHP中防止SQL注入攻击和XSS攻击的两个简单方法
Apr 15 PHP
PHP ? EasyUI DataGrid 资料取的方式介绍
Nov 07 PHP
浅析php学习的路线图
Jul 10 PHP
php插入排序法实现数组排序实例
Feb 16 PHP
ThinkPHP文件缓存类代码分享
Apr 22 PHP
php结合mysql与mysqli扩展处理事务的方法
Jun 29 PHP
Yii中的cookie的发送和读取
Jul 27 PHP
PHP利用正则表达式将相对路径转成绝对路径的方法示例
Feb 28 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
Flash空降上海 化身大魔王接受挑战
2020/03/02 星际争霸
解析CodeIgniter自定义配置文件
2013/06/18 PHP
本地机apache配置基于域名的虚拟主机详解
2013/08/10 PHP
PHP上传图片、删除图片简单实例
2016/11/12 PHP
php从数据库读取数据,并以json格式返回数据的方法
2018/08/21 PHP
Laravel使用Queue队列的技巧汇总
2019/09/02 PHP
js 表单验证方法(实用)
2009/04/28 Javascript
5个JavaScript经典面试题
2014/10/13 Javascript
$.extend 的一个小问题
2015/06/18 Javascript
JavaScript清空数组元素的两种方法简单比较
2015/07/10 Javascript
JS实现的简洁二级导航菜单雏形效果
2015/10/13 Javascript
Validform表单验证总结篇
2016/10/31 Javascript
WebPack基础知识详解
2017/01/16 Javascript
浅谈angular2的http请求返回结果的subcribe注意事项
2017/03/01 Javascript
Bootstrap 响应式实用工具实例详解
2017/03/29 Javascript
让div运动起来 js实现缓动效果
2017/07/06 Javascript
Vue项目中使用WebUploader实现文件上传的方法
2019/07/21 Javascript
py2exe 编译ico图标的代码
2013/03/08 Python
Python使用metaclass实现Singleton模式的方法
2015/05/05 Python
python实现的系统实用log类实例
2015/06/30 Python
python 读文件,然后转化为矩阵的实例
2018/04/23 Python
Python字典创建 遍历 添加等实用基础操作技巧
2018/09/13 Python
Python matplotlib生成图片背景透明的示例代码
2019/08/30 Python
Python3实现发送邮件和发送短信验证码功能
2020/01/07 Python
python新手学习可变和不可变对象
2020/06/11 Python
VSCODE配置Markdown及Markdown基础语法详解
2021/01/19 Python
详解canvas在圆弧周围绘制文本的两种写法
2018/05/22 HTML / CSS
Herschel美国官网:背包、手提袋及配件
2020/03/10 全球购物
给幼儿园老师的表扬信
2014/01/19 职场文书
大学同学聚会邀请函
2014/01/19 职场文书
动员大会主持词
2014/03/20 职场文书
健康家庭事迹材料
2014/05/02 职场文书
施工工地安全标语
2014/06/07 职场文书
高考升学宴主持词
2019/06/21 职场文书
Python图像处理之图像拼接
2021/04/28 Python
Oracle中DBLink的详细介绍
2022/04/29 Oracle