論在用PHP寫反向代理/CDN時遇到的坑

最近有人說我站點(diǎn)打開速度慢,防御還差,我就忍不住了,當(dāng)場就準(zhǔn)備寫一個可以部署在空間的CDN程序

當(dāng)然,在此之前,我也上GayHub搜了一下有沒有現(xiàn)成的CDN軟件,找到了一個,有興趣的朋友可以去搜搜LayerCDN。但是為什么不用呢,因?yàn)楹芏喙δ苋鐐鬟fPOST參數(shù)和COOKIE都沒有(粗略的看了下源碼看到的),于是了解了一下原理(cURL)后開始自己搗鼓

既然知道了原理,那實(shí)現(xiàn)起來就沒有太大的難度了

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

說實(shí)話這也還是我第一次用cURL來寫應(yīng)用,之前有遇到要請求httpapi的項(xiàng)目用的都是file_get_contents,當(dāng)時已經(jīng)滿足了條件。但是現(xiàn)在要做的可是CDN,單純的獲取已經(jīng)滿足不了需求了,何況FGC不會緩存dns,再次訪問還需要解析,因此直接放棄FGC

一開始使curl的時候發(fā)現(xiàn)無法輸出,網(wǎng)上查閱很久沒找到解決方案,于是暫時改用FGC,這是遇到的第一個坑。后來直接用了他人的實(shí)例便可以了,如下(已化簡到最簡)

<?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也遇到了問題,便是沒有設(shè)置Content-type,瀏覽器默認(rèn)把css/js/圖片等文件全作為html來解析,一開始想的解決方案比較麻煩,但是確實(shí)解決了

<?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');

}

后來因?yàn)橛龅搅薖HP動態(tài)生成的驗(yàn)證碼,做適配不太容易,因此去找了一下獲取Mine-type的curl方法,還真有,于是上面的代碼就注釋掉了

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

由于header需要在傳輸內(nèi)容前設(shè)置,所以第一個curl實(shí)例需要改改

$r=curl_exec($ch);

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

echo $r;

curl_close($ch);

但是這也解決不了我說遇到的問題,還在研究,但相對窮舉這個方法無疑更加簡便,效率更高

復(fù)制COOKIE也是一個重要功能,很多程序依賴于COOKIE,比如cloudflare,和PHP的SESSION,所以這個功能也是不可或缺的

下一個遇到的坑便是獲取curl后源站給cdn服務(wù)器設(shè)置的cookie,一開始想用header獲取的,直接設(shè)置header即可,這個方法確實(shí)一勞永逸,但是發(fā)現(xiàn)找到的很臃腫,于是繼續(xù)摸索,找到了將cookie寫進(jìn)文件的方法,也就是COOKIEJAR這可是個大坑,不僅無法實(shí)現(xiàn)功能,而且還獲取不到COOKIE

于是換個關(guān)鍵詞繼續(xù)百度php curl獲取cookie

找到

curl_getinfo($ch, CURLINFO_COOKIELIST);

返回的是一個數(shù)組,每個cookie為一個元素,處理一下,并設(shè)置cookie

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

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

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

}

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

獲取到并給用戶設(shè)置完以后就很簡單了

在用戶訪問cdn節(jié)點(diǎn)的時候判斷有沒有設(shè)置cookie,有就寫進(jìn)curl

if($_COOKIE){

? ? $ucookie;

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

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

? ? }

? ? curl_setopt($ch, CURLOPT_COOKIE, $ucookie);

}

至此COOKIE復(fù)制就可以了

其實(shí)POST轉(zhuǎn)發(fā)應(yīng)該放前面的,畢竟比較重要,但是并沒有踩到什么坑,因此這樣安排

if($_POST){

? ? curl_setopt($ch, CURLOPT_POST, 1);

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

}

這就沒啥好說的了,這樣就可以

在實(shí)踐中還碰到了資源是絕對鏈接的情況,也有特殊的如dz使用了base標(biāo)簽(一開始還搞得我一頭霧水,明明源碼是相對鏈接,點(diǎn)開卻是絕對的),對于這種,用以下方法可以解決。

原理:將所有該站點(diǎn)的絕對鏈接換成相對

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

echo $r;

是否采用https具體情況具體考慮

此外,不驗(yàn)證SSL可以提高回源速度

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

完整的源碼待開發(fā)完后會貼出,也會開源,敬請關(guān)注


轉(zhuǎn)自本人的博客

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容