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 相关文章推荐
BBS(php &amp; mysql)完整版(六)
Oct 09 PHP
smarty+adodb+部分自定义类的php开发模式
Dec 31 PHP
PHP入门学习的几个不错的实例代码
Jul 13 PHP
php网站来路获取代码(针对搜索引擎)
Jun 08 PHP
PHP可逆加密/解密函数分享
Sep 25 PHP
PHP中比较时间大小实例
Aug 21 PHP
php从文件夹随机读取文件的方法
Jun 01 PHP
WordPress中编写自定义存储字段的相关PHP函数解析
Dec 25 PHP
PHP中header函数的用法及其注意事项详解
Jun 13 PHP
thinkPHP框架实现多表查询的方法
Jun 14 PHP
php文件操作之文件写入字符串、数组的方法分析
Apr 15 PHP
使用laravel的Eloquent模型如何获取数据库的指定列
Oct 17 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常用函数 推荐收藏保存
2010/02/21 PHP
php学习之 数组声明
2011/06/09 PHP
PHP实现事件机制的方法
2015/07/10 PHP
ZendFramework2连接数据库操作实例
2017/04/18 PHP
在laravel中实现将查询的对象转换为多维数组的函数
2019/10/21 PHP
Javascript打印网页部分内容的脚本
2008/11/17 Javascript
在线编辑器中换行与内容自动提取
2009/04/24 Javascript
JS实现很酷的EMAIL地址添加功能实例
2015/02/28 Javascript
JavaScript中指定函数名称的相关方法
2015/06/04 Javascript
JS日期对象简单操作(获取当前年份、星期、时间)
2016/10/26 Javascript
详解如何在NodeJS项目中优雅的使用ES6
2017/04/22 NodeJs
温故知新——JavaScript中的字符串连接问题最全总结(推荐)
2017/08/21 Javascript
vue 属性拦截实现双向绑定的实例代码
2018/10/24 Javascript
JS+php后台实现文件上传功能详解
2019/03/02 Javascript
jquery实现购物车基本功能
2019/10/25 jQuery
Vue+Node实现商品列表的分页、排序、筛选,添加购物车功能详解
2019/12/07 Javascript
viewer.js实现图片预览功能
2020/06/24 Javascript
python实现百度关键词排名查询
2014/03/30 Python
python实现简单socket程序在两台电脑之间传输消息的方法
2015/03/13 Python
Python使用tablib生成excel文件的简单实现方法
2016/03/16 Python
Python使用中文正则表达式匹配指定中文字符串的方法示例
2017/01/20 Python
Python cookbook(数据结构与算法)找到最大或最小的N个元素实现方法示例
2018/02/13 Python
python 使用 requests 模块发送http请求 的方法
2018/12/09 Python
Windows10下Tensorflow2.0 安装及环境配置教程(图文)
2019/11/21 Python
Python sorted排序方法如何实现
2020/03/31 Python
Canvas环形饼图与手势控制的实现代码
2019/11/08 HTML / CSS
西班牙鞋子和箱包在线销售网站:zapatos.es
2020/02/17 全球购物
描述Cookie和Session的作用,区别和各自的应用范围,Session工作原理
2015/03/25 面试题
EJB面试题
2015/07/28 面试题
教育孩子心得体会
2014/01/01 职场文书
一位农村小子的自荐信
2014/04/07 职场文书
学生检讨书怎么写
2014/10/09 职场文书
村党建工作汇报材料
2014/11/02 职场文书
2014年学校教学工作总结
2014/12/06 职场文书
新员工入职感言范文!
2019/07/04 职场文书
为什么MySQL8新特性会修改自增主键属性
2022/04/18 MySQL