今天我們來看以下兩個現(xiàn)象近上,并解釋這兩個現(xiàn)象的原因:
第一個現(xiàn)象:
?php文件運(yùn)行過程中如果碰到有header("Location:某個頁面URL");這種語句抚垄,會直接跳轉(zhuǎn)到另一個頁面,但是這里的跳轉(zhuǎn)并不會影響當(dāng)前php文件的繼續(xù)執(zhí)行。
下面我們用代碼跑一下看看上面的現(xiàn)象是否是成立的:
(1)http://a.com/test.php代碼如下:
(2)http://b.com/test.php代碼如下:
(3)訪問http://a.com/test.php顯示以下結(jié)果:
此時魏宽,我們發(fā)現(xiàn)我們顯示的結(jié)果頁中,地址欄變成了b.com/test.php决乎,同時队询,頁面輸出了123,然后我們也看到a.com下面cookie被寫入成功了构诚,而且a.txt文件也生成了蚌斩。
實驗證明,header302跳轉(zhuǎn)之后范嘱,其下面的代碼還是會繼續(xù)執(zhí)行送膳,那么原因是什么呢员魏?
很多人不明白,不是已經(jīng)跳轉(zhuǎn)走了嗎叠聋?跳走了怎么可能還執(zhí)行撕阎?
要解釋這個現(xiàn)象其實原理很簡單,客戶端a向服務(wù)端b發(fā)送請求碌补,服務(wù)端b處理完成之后虏束,響應(yīng)回客戶端a。注意這里面的用詞厦章,處理完成镇匀!處理完成!處理完成袜啃!是服務(wù)端b處理完成之后才會響應(yīng)客戶端汗侵。
上代碼,我們證實一下是不是處理完成之后響應(yīng)回客戶端:
(1)http://a.com/test.php代碼如下:
(2)http://b.com/test.php代碼不變?nèi)缦拢?br>
(3)訪問http://a.com/test.php顯示以下結(jié)果:
瀏覽器一直在加載群发,10秒之后才跳轉(zhuǎn)到http://b.com/test.php頁面晰韵。
上圖中代碼寫的很清楚,先header跳轉(zhuǎn)然后在sleep(10)也物,頁面沒有立即跳轉(zhuǎn)而是停了10秒鐘再發(fā)生跳轉(zhuǎn)宫屠。
所以要想header之后代碼不繼續(xù)執(zhí)行,我們只需要在header后面exit就可以了滑蚯,代碼如下:
那么后面的代碼就不會被執(zhí)行浪蹂!
到這個地方,我們第一個現(xiàn)象的原因其實已經(jīng)解釋完了告材,現(xiàn)在我們來看一個細(xì)節(jié)坤次,http://a.com/test.php代碼如下圖一所示,訪問http://a.com/test.php響應(yīng)回來的內(nèi)容為空斥赋,見下圖二缰猴,我們雖然有echo 有print_r還有var_dump,但是都沒有被輸出疤剑。
通過谷歌瀏覽器滑绒,我們看到服務(wù)端雖然沒有返回內(nèi)容,但是返回了響應(yīng)消息頭隘膘,如下:
由此看來疑故,當(dāng)服務(wù)器端在設(shè)置header響應(yīng)報文給客戶端的時候,如果狀態(tài)碼是302弯菊,那么服務(wù)器端就不會返回具體的數(shù)據(jù)內(nèi)容給客戶端纵势,而瀏覽器看到302,也不用去關(guān)心返回的響應(yīng)內(nèi)容,直接拿著響應(yīng)報文里面的location地址前往下一站去嘍钦铁,這樣的方式也防止了不必要的數(shù)據(jù)傳輸软舌。
這讓我想到了另一張情況,客戶端去情況求服務(wù)端的時候牛曹,服務(wù)端驗證請求資源沒有發(fā)生改變會返回304狀態(tài)碼佛点,那么這個時候服務(wù)器端也不會返回響應(yīng)內(nèi)容,通過304狀態(tài)碼去告訴瀏覽器躏仇,這個資源沒有更改過恋脚,你直接從自己的緩存中去拿吧。
我們繼續(xù)第二個現(xiàn)象:
?header 302跳轉(zhuǎn)可以跳轉(zhuǎn)到其他網(wǎng)站設(shè)置cookie而curl無法給其他站點設(shè)置cookie焰手,這又是為什么?
在之前怀喉,我們其實探討過這個問題jsonp系列(三)兩種寫法請求后端設(shè)置cookie书妻,為啥一個可以,一個不可以躬拢?躲履,其中我們講到了,為什么curl不能跨站設(shè)置cookie,但是今天有小伙伴問聊闯,為啥工猜,header 跳轉(zhuǎn)能夠給其他站點設(shè)置cookie呢?
還是先看代碼吧:
(1)http://a.com/test.php代碼如下:
(2)http://b.com/test.php代碼如下:
(3)訪問http://a.com/test.php我們發(fā)現(xiàn)頁面跳轉(zhuǎn)到http://b.com/test.php并且b.com下被設(shè)置了cookie菱蔬。
這又是什么原因呢篷帅?
為啥curl不可以,header302卻可以?
通過谷歌瀏覽器我們可以發(fā)現(xiàn):
如圖中所示拴泌,當(dāng)我們在地址欄敲下http://a.com/test.php并且敲下回車的時候魏身,通過谷歌瀏覽器我們發(fā)現(xiàn)了兩個請求都是test.php,分別如下:
如上圖蚪腐,當(dāng)瀏覽器去請求http://a.com/test.php的時候箭昵,a.com服務(wù)端返回302給瀏覽器,瀏覽器拿到響應(yīng)消息頭的location回季,存到內(nèi)存中家制,此時瀏覽器與http://a.com的通信過程其實就結(jié)束了,也就是一個請求與響應(yīng)就結(jié)束了泡一,然后瀏覽器拿著location地址重新請求http://b.com/test.php颤殴,于是我們看到瀏覽器跳轉(zhuǎn)的畫面,此時b瘾杭。com返回給瀏覽器的響應(yīng)消息頭里面有set-cookie的信息诅病,那么瀏覽器得到這個cookie信息生成文件并存放到了瀏覽器默認(rèn)cookie存放的目錄下。
如圖所示:
header跳轉(zhuǎn)的情況:
在第6個步驟中,b.com返回了cookie信息給瀏覽器贤笆,瀏覽器存下了b.com的cookie信息蝇棉。
curl請求的情況:
在第6步中,b.com將cookie信息返回給a.com服務(wù)器芥永,但是a.com服務(wù)器并沒有把cookie信息交給瀏覽器篡殷,所以瀏覽器最終沒能寫下b.com的cookie信息。
由此可見埋涧,為啥header可以設(shè)置b.com的cookie板辽,而curl不能設(shè)置b.com的cookie在于,header的時候棘催,服務(wù)端把cookie信息給了瀏覽器劲弦,而curl的時候,b.com把cookie給了a.com服務(wù)器醇坝,并沒有給到瀏覽器邑跪,所以最終一個設(shè)置cookie成功,一個設(shè)置cookie失敗呼猪。