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 UTF-8、Unicode和BOM问题
May 18 PHP
php URL验证正则表达式
Jul 19 PHP
PHP中“简单工厂模式”实例代码讲解
Sep 04 PHP
ThinkPHP3.1新特性之多数据库操作更加完善
Jun 19 PHP
ThinkPHP3.1.3版本新特性概述
Jun 19 PHP
php中使用array_filter()函数过滤空数组的实现代码
Aug 19 PHP
php5.4以下版本json不支持不转义内容中文的解决方法
Jan 13 PHP
ThinkPHP中session函数详解
Sep 14 PHP
PHP实现字符串的全排列详解
Apr 24 PHP
laravel 如何实现引入自己的函数或类库
Oct 15 PHP
PHP全局使用Laravel辅助函数dd
Dec 26 PHP
phpStudy vscode 搭建debug调试的教程详解
Jul 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
建立动态的WML站点(一)
2006/10/09 PHP
我的群发邮件程序
2006/10/09 PHP
php设计模式之委托模式
2016/02/13 PHP
PHP使用mysql与mysqli连接Mysql数据库用法示例
2016/07/07 PHP
php基于闭包实现函数的自调用(递归)实例分析
2016/11/11 PHP
js Flash插入函数免激活代码
2009/03/31 Javascript
jsonp原理及使用
2013/10/28 Javascript
单元选择合并变色示例代码
2014/05/26 Javascript
利用jQuery实现可以编辑的表格
2014/05/26 Javascript
JS中使用 after 伪类清除浮动实例
2017/03/01 Javascript
Node.js 中exports 和 module.exports 的区别
2017/03/14 Javascript
jQuery实现移动端Tab选项卡效果
2017/03/15 Javascript
Nodejs+angularjs结合multiparty实现多图片上传的示例代码
2017/09/29 NodeJs
angular2实现统一的http请求头方法
2018/08/13 Javascript
Vue弹出菜单功能的实现代码
2018/09/12 Javascript
mpvue性能优化实战技巧(小结)
2019/04/17 Javascript
Vue Autocomplete 自动完成功能简单示例
2019/05/25 Javascript
JavaScript enum枚举类型定义及使用方法
2020/05/15 Javascript
jQuery实现计算器功能
2020/10/19 jQuery
[02:17]2016国际邀请赛中国区预选赛VG战队领队采访
2016/06/26 DOTA
Python学习笔记之常用函数及说明
2014/05/23 Python
Python socket C/S结构的聊天室应用实现
2014/11/30 Python
python使用正则表达式替换匹配成功的组并输出替换的次数
2017/11/22 Python
详解Python匿名函数(lambda函数)
2019/04/19 Python
python+logging+yaml实现日志分割
2019/07/22 Python
Python如何使用Gitlab API实现批量的合并分支
2019/11/27 Python
Tensorflow实现部分参数梯度更新操作
2020/01/23 Python
Html5移动端适配IphoneX等机型的方法
2019/06/25 HTML / CSS
PHP如何去执行一个SQL语句
2016/03/05 面试题
高中学生评语大全
2014/04/25 职场文书
争先创优公开承诺书
2014/08/30 职场文书
幼儿园教师师德表现自我评价
2015/03/05 职场文书
公务员处分决定书
2015/06/25 职场文书
python内置进制转换函数的操作
2021/06/02 Python
关于Python使用turtle库画任意图的问题
2022/04/01 Python
Java 关于String字符串原理上的问题
2022/04/07 Java/Android