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 相关文章推荐
15个小时----从修改程序到自己些程序
Oct 09 PHP
php下将图片以二进制存入mysql数据库中并显示的实现代码
May 27 PHP
ThinkPHP采用模块和操作分析
Apr 18 PHP
PHP用身份证号获取星座和生肖的方法
Nov 07 PHP
ThinkPHP使用PHPExcel实现Excel数据导入导出完整实例
Jul 22 PHP
php实现的支持imagemagick及gd库两种处理的缩略图生成类
Sep 23 PHP
PHP调用MySQL存储过程并返回值的方法
Dec 26 PHP
php简单分页类实现方法
Feb 26 PHP
PHP常见漏洞攻击分析
Feb 21 PHP
php基于websocket搭建简易聊天室实践
Oct 24 PHP
PHP实现分布式memcache设置web集群session同步的方法
Apr 10 PHP
PHP5中使用mysqli的prepare操作数据库的介绍
Mar 18 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 EOT定界符的使用详解
2008/09/30 PHP
php图片加水印原理(超简单的实例代码)
2013/01/18 PHP
php的$_FILES的临时储存文件与回收机制实测过程
2013/07/12 PHP
PHP实现的登录页面信息提示功能示例
2017/07/24 PHP
PHP迭代器接口Iterator用法分析
2017/12/28 PHP
ExtJS 简介 让你知道extjs是什么
2008/12/29 Javascript
获取非最后一列td值并将title设为该值的方法
2013/10/30 Javascript
写出高效jquery代码的19条指南
2014/03/19 Javascript
jquery通过load获取文件的内容并跳到锚点的方法
2015/01/29 Javascript
director.js实现前端路由使用实例
2015/02/03 Javascript
jquery UI Datepicker时间控件冲突问题解决
2016/12/16 Javascript
jQuery纵向导航菜单效果实现方法
2016/12/19 Javascript
javascript设计模式之单体模式学习笔记
2017/02/15 Javascript
深入理解在JS中通过四种设置事件处理程序的方法
2017/03/02 Javascript
详解使用vscode+es6写nodejs服务端调试配置
2017/09/21 NodeJs
详解如何使用babel进行es6文件的编译
2018/05/29 Javascript
JavaScript生成一个不重复的ID的方法示例
2019/09/16 Javascript
在Python中操作文件之seek()方法的使用教程
2015/05/24 Python
Python使用爬虫猜密码
2016/02/19 Python
Python复数属性和方法运算操作示例
2017/07/21 Python
Python中支持向量机SVM的使用方法详解
2017/12/26 Python
火车票抢票python代码公开揭秘!
2018/03/08 Python
攻击者是如何将PHP Phar包伪装成图像以绕过文件类型检测的(推荐)
2018/10/11 Python
python读取Excel表格文件的方法
2019/09/02 Python
Python之指数与E记法的区别详解
2019/11/21 Python
Ubuntu20.04环境安装tensorflow2的方法步骤
2021/01/29 Python
分享一个H5原生form表单的checkbox特效代码
2018/02/26 HTML / CSS
HTML5 Canvas画线技巧——实现绘制一个像素宽的细线
2013/08/02 HTML / CSS
医药学专业大学生职业生涯规划书论文
2014/01/21 职场文书
广告语设计及教案
2014/03/21 职场文书
财产公证书格式
2014/04/10 职场文书
宣传部部长竞选演讲稿
2014/04/26 职场文书
九一八事变演讲稿范文
2014/09/14 职场文书
综合素质评价个性与发展自我评价
2015/03/06 职场文书
写给导师的自荐信
2015/03/06 职场文书
使用redis生成唯一编号及原理示例详解
2021/09/15 Redis