今天我們來(lái)看以下兩個(gè)現(xiàn)象,并解釋這兩個(gè)現(xiàn)象的原因:
第一個(gè)現(xiàn)象:
?php文件運(yùn)行過(guò)程中如果碰到有header("Location:某個(gè)頁(yè)面URL");這種語(yǔ)句,會(huì)直接跳轉(zhuǎn)到另一個(gè)頁(yè)面,但是這里的跳轉(zhuǎn)并不會(huì)影響當(dāng)前php文件的繼續(xù)執(zhí)行。
下面我們用代碼跑一下看看上面的現(xiàn)象是否是成立的:
(1)http://a.com/test.php代碼如下:

(2)http://b.com/test.php代碼如下:

(3)訪問(wèn)http://a.com/test.php顯示以下結(jié)果:

此時(shí),我們發(fā)現(xiàn)我們顯示的結(jié)果頁(yè)中,地址欄變成了b.com/test.php,同時(shí),頁(yè)面輸出了123,然后我們也看到a.com下面cookie被寫(xiě)入成功了,而且a.txt文件也生成了。
實(shí)驗(yàn)證明,header302跳轉(zhuǎn)之后,其下面的代碼還是會(huì)繼續(xù)執(zhí)行,那么原因是什么呢?
很多人不明白,不是已經(jīng)跳轉(zhuǎn)走了嗎?跳走了怎么可能還執(zhí)行?
要解釋這個(gè)現(xiàn)象其實(shí)原理很簡(jiǎn)單,客戶端a向服務(wù)端b發(fā)送請(qǐng)求,服務(wù)端b處理完成之后,響應(yīng)回客戶端a。注意這里面的用詞,處理完成!處理完成!處理完成!是服務(wù)端b處理完成之后才會(huì)響應(yīng)客戶端。
上代碼,我們證實(shí)一下是不是處理完成之后響應(yīng)回客戶端:
(1)http://a.com/test.php代碼如下:

(2)http://b.com/test.php代碼不變?nèi)缦拢?br>

(3)訪問(wèn)http://a.com/test.php顯示以下結(jié)果:

瀏覽器一直在加載,10秒之后才跳轉(zhuǎn)到http://b.com/test.php頁(yè)面。
上圖中代碼寫(xiě)的很清楚,先header跳轉(zhuǎn)然后在sleep(10),頁(yè)面沒(méi)有立即跳轉(zhuǎn)而是停了10秒鐘再發(fā)生跳轉(zhuǎn)。
所以要想header之后代碼不繼續(xù)執(zhí)行,我們只需要在header后面exit就可以了,代碼如下:

那么后面的代碼就不會(huì)被執(zhí)行!
到這個(gè)地方,我們第一個(gè)現(xiàn)象的原因其實(shí)已經(jīng)解釋完了,現(xiàn)在我們來(lái)看一個(gè)細(xì)節(jié),http://a.com/test.php代碼如下圖一所示,訪問(wèn)http://a.com/test.php響應(yīng)回來(lái)的內(nèi)容為空,見(jiàn)下圖二,我們雖然有echo 有print_r還有var_dump,但是都沒(méi)有被輸出。


通過(guò)谷歌瀏覽器,我們看到服務(wù)端雖然沒(méi)有返回內(nèi)容,但是返回了響應(yīng)消息頭,如下:

由此看來(lái),當(dāng)服務(wù)器端在設(shè)置header響應(yīng)報(bào)文給客戶端的時(shí)候,如果狀態(tài)碼是302,那么服務(wù)器端就不會(huì)返回具體的數(shù)據(jù)內(nèi)容給客戶端,而瀏覽器看到302,也不用去關(guān)心返回的響應(yīng)內(nèi)容,直接拿著響應(yīng)報(bào)文里面的location地址前往下一站去嘍,這樣的方式也防止了不必要的數(shù)據(jù)傳輸。
這讓我想到了另一張情況,客戶端去情況求服務(wù)端的時(shí)候,服務(wù)端驗(yàn)證請(qǐng)求資源沒(méi)有發(fā)生改變會(huì)返回304狀態(tài)碼,那么這個(gè)時(shí)候服務(wù)器端也不會(huì)返回響應(yīng)內(nèi)容,通過(guò)304狀態(tài)碼去告訴瀏覽器,這個(gè)資源沒(méi)有更改過(guò),你直接從自己的緩存中去拿吧。
我們繼續(xù)第二個(gè)現(xiàn)象:
?header 302跳轉(zhuǎn)可以跳轉(zhuǎn)到其他網(wǎng)站設(shè)置cookie而curl無(wú)法給其他站點(diǎn)設(shè)置cookie,這又是為什么?
在之前,我們其實(shí)探討過(guò)這個(gè)問(wèn)題jsonp系列(三)兩種寫(xiě)法請(qǐng)求后端設(shè)置cookie,為啥一個(gè)可以,一個(gè)不可以?,其中我們講到了,為什么curl不能跨站設(shè)置cookie,但是今天有小伙伴問(wèn),為啥,header 跳轉(zhuǎn)能夠給其他站點(diǎn)設(shè)置cookie呢?
還是先看代碼吧:
(1)http://a.com/test.php代碼如下:

(2)http://b.com/test.php代碼如下:

(3)訪問(wèn)http://a.com/test.php我們發(fā)現(xiàn)頁(yè)面跳轉(zhuǎn)到http://b.com/test.php并且b.com下被設(shè)置了cookie。
這又是什么原因呢?
為啥curl不可以,header302卻可以?
通過(guò)谷歌瀏覽器我們可以發(fā)現(xiàn):

如圖中所示,當(dāng)我們?cè)诘刂窓谇孟耯ttp://a.com/test.php并且敲下回車(chē)的時(shí)候,通過(guò)谷歌瀏覽器我們發(fā)現(xiàn)了兩個(gè)請(qǐng)求都是test.php,分別如下:


如上圖,當(dāng)瀏覽器去請(qǐng)求http://a.com/test.php的時(shí)候,a.com服務(wù)端返回302給瀏覽器,瀏覽器拿到響應(yīng)消息頭的location,存到內(nèi)存中,此時(shí)瀏覽器與http://a.com的通信過(guò)程其實(shí)就結(jié)束了,也就是一個(gè)請(qǐng)求與響應(yīng)就結(jié)束了,然后瀏覽器拿著location地址重新請(qǐng)求http://b.com/test.php,于是我們看到瀏覽器跳轉(zhuǎn)的畫(huà)面,此時(shí)b。com返回給瀏覽器的響應(yīng)消息頭里面有set-cookie的信息,那么瀏覽器得到這個(gè)cookie信息生成文件并存放到了瀏覽器默認(rèn)cookie存放的目錄下。
如圖所示:
header跳轉(zhuǎn)的情況:

在第6個(gè)步驟中,b.com返回了cookie信息給瀏覽器,瀏覽器存下了b.com的cookie信息。
curl請(qǐng)求的情況:

在第6步中,b.com將cookie信息返回給a.com服務(wù)器,但是a.com服務(wù)器并沒(méi)有把cookie信息交給瀏覽器,所以瀏覽器最終沒(méi)能寫(xiě)下b.com的cookie信息。
由此可見(jiàn),為啥header可以設(shè)置b.com的cookie,而curl不能設(shè)置b.com的cookie在于,header的時(shí)候,服務(wù)端把cookie信息給了瀏覽器,而curl的時(shí)候,b.com把cookie給了a.com服務(wù)器,并沒(méi)有給到瀏覽器,所以最終一個(gè)設(shè)置cookie成功,一個(gè)設(shè)置cookie失敗。