论在用PHP写反向代理/CDN时遇到的坑

最近有人说我站点打开速度慢,防御还差,我就忍不住了,当场就准备写一个可以部署在空间的CDN程序

当然,在此之前,我也上GayHub搜了一下有没有现成的CDN软件,找到了一个,有兴趣的朋友可以去搜搜LayerCDN。但是为什么不用呢,因为很多功能如传递POST参数和COOKIE都没有(粗略的看了下源码看到的),于是了解了一下原理(cURL)后开始自己捣鼓

既然知道了原理,那实现起来就没有太大的难度了

打开百度,搜索php curl,开始摸索

说实话这也还是我第一次用cURL来写应用,之前有遇到要请求httpapi的项目用的都是file_get_contents,当时已经满足了条件。但是现在要做的可是CDN,单纯的获取已经满足不了需求了,何况FGC不会缓存dns,再次访问还需要解析,因此直接放弃FGC

一开始使curl的时候发现无法输出,网上查阅很久没找到解决方案,于是暂时改用FGC,这是遇到的第一个坑。后来直接用了他人的实例便可以了,如下(已化简到最简)

<?php

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL,'https://www.mcplugin.cn'.$_SERVER['REQUEST_URI']);

curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

echo curl_exec($ch);

curl_close($ch);

使用FGC也遇到了问题,便是没有设置Content-type,浏览器默认把css/js/图片等文件全作为html来解析,一开始想的解决方案比较麻烦,但是确实解决了

<?php

switch(end(explode('.',$_SERVER['REDIRECT_URL']))){

    case 'js': header('Content-type: text/javascript'); break;

    case 'css': header('Content-type: text/css'); break;

    case 'png': header('Content-type: image/png'); break;

    case 'gif': header('Content-type: image/gif'); break;

    case 'jpg': case 'jpeg': header('Content-type: image/jpeg'); break;

    case 'svg': header('Content-type: image/svg+xml'); break;

    case 'mp3': header('Content-type: audio/mpeg'); break;

    case 'txt': header('Content-type: text/plain'); break;

    //case '': header('Content-type: '); break;

    default: header('Content-Type: text/html');

}

后来因为遇到了PHP动态生成的验证码,做适配不太容易,因此去找了一下获取Mine-type的curl方法,还真有,于是上面的代码就注释掉了

header('Content-type: '.curl_getinfo($ch, CURLINFO_CONTENT_TYPE));

由于header需要在传输内容前设置,所以第一个curl实例需要改改

$r=curl_exec($ch);

header('Content-type: '.curl_getinfo($ch, CURLINFO_CONTENT_TYPE));

echo $r;

curl_close($ch);

但是这也解决不了我说遇到的问题,还在研究,但相对穷举这个方法无疑更加简便,效率更高

复制COOKIE也是一个重要功能,很多程序依赖于COOKIE,比如cloudflare,和PHP的SESSION,所以这个功能也是不可或缺的

下一个遇到的坑便是获取curl后源站给cdn服务器设置的cookie,一开始想用header获取的,直接设置header即可,这个方法确实一劳永逸,但是发现找到的很臃肿,于是继续摸索,找到了将cookie写进文件的方法,也就是COOKIEJAR这可是个大坑,不仅无法实现功能,而且还获取不到COOKIE

于是换个关键词继续百度php curl获取cookie

找到

curl_getinfo($ch, CURLINFO_COOKIELIST);

返回的是一个数组,每个cookie为一个元素,处理一下,并设置cookie

foreach(curl_getinfo($ch, CURLINFO_COOKIELIST) as $scookie){

    $scookie=explode("\t",$scookie);

    setcookie($scookie[5],$scookie[6],$scookie[4]);

}

用兴趣想看看是什么可以print_r查看

获取到并给用户设置完以后就很简单了

在用户访问cdn节点的时候判断有没有设置cookie,有就写进curl

if($_COOKIE){

    $ucookie;

    foreach($_COOKIE as $utcn=>$utcv){

        $ucookie.=$utcn.'='.$utcv.';';

    }

    curl_setopt($ch, CURLOPT_COOKIE, $ucookie);

}

至此COOKIE复制就可以了

其实POST转发应该放前面的,毕竟比较重要,但是并没有踩到什么坑,因此这样安排

if($_POST){

    curl_setopt($ch, CURLOPT_POST, 1);

    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($_POST));

}

这就没啥好说的了,这样就可以

在实践中还碰到了资源是绝对链接的情况,也有特殊的如dz使用了base标签(一开始还搞得我一头雾水,明明源码是相对链接,点开却是绝对的),对于这种,用以下方法可以解决。

原理:将所有该站点的绝对链接换成相对

$r=str_replace('//www.mcplugin.cn','',str_replace('https://www.mcplugin.cn','',curl_exec($ch)));

echo $r;

是否采用https具体情况具体考虑

此外,不验证SSL可以提高回源速度

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

完整的源码待开发完后会贴出,也会开源,敬请关注


转自本人的博客

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,001评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,210评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,874评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,001评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,022评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,005评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,929评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,742评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,193评论 1 309
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,427评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,583评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,305评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,911评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,564评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,731评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,581评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,478评论 2 352

推荐阅读更多精彩内容