詳解重定向(HTTP狀態(tài)碼301/302/303/307/308)附案例
關(guān)注 前端瓶子君,回復(fù)“交流”
加入我們一起學(xué)習(xí),天天進(jìn)步

今天打算好好把狀態(tài)碼301、302、303、307、308好好擼一遍,并會測試下一些例子。
狀態(tài)碼的解釋
我們都知道重定向與這幾種狀態(tài)碼有關(guān),來看下這幾種HTTP狀態(tài)碼的解釋(摘自維基百科)
301 Moved Permanently(永久移動)
被請求的資源已永久移動到新位置,并且將來任何對此資源的引用都應(yīng)該使用本響應(yīng)返回的若干個URI之一。
如果可能,擁有鏈接編輯功能的客戶端應(yīng)當(dāng)自動把請求的地址修改為從服務(wù)器反饋回來的地址。
除非額外指定,否則這個響應(yīng)也是可緩存的。新的永久性的URI應(yīng)當(dāng)在響應(yīng)的Location域中返回。除非這是一個HEAD請求,否則響應(yīng)的實體中應(yīng)當(dāng)包含指向新的URI的超鏈接及簡短說明。如果這不是一個GET或者HEAD請求,因此瀏覽器禁止自動進(jìn)行重定向,除非得到用戶的確認(rèn),因為請求的條件可能因此發(fā)生變化。
注意:對于某些使用HTTP/1.0協(xié)議的瀏覽器,當(dāng)它們發(fā)送的POST請求得到了一個301響應(yīng)的話,接下來的重定向請求將會變成GET方式。

302 Found(發(fā)現(xiàn))
要求客戶端執(zhí)行臨時重定向(原始描述短語為“Moved Temporarily”)。
由于這樣的重定向是臨時的,客戶端應(yīng)當(dāng)繼續(xù)向原有地址發(fā)送以后的請求。
只有在Cache-Control或Expires中進(jìn)行了指定的情況下,這個響應(yīng)才是可緩存的。新的臨時性的URI應(yīng)當(dāng)在響應(yīng)的Location域中返回。除非這是一個HEAD請求,否則響應(yīng)的實體中應(yīng)當(dāng)包含指向新的URI的超鏈接及簡短說明。如果這不是一個GET或者HEAD請求,那么瀏覽器禁止自動進(jìn)行重定向,除非得到用戶的確認(rèn),因為請求的條件可能因此發(fā)生變化。
注意:雖然RFC 1945和RFC 2068規(guī)范不允許客戶端在重定向時改變請求的方法,但是很多現(xiàn)存的瀏覽器將302響應(yīng)視作為303響應(yīng),并且使用GET方式訪問在Location中規(guī)定的URI,而無視原先請求的方法。因此狀態(tài)碼303和307被添加了進(jìn)來,用以明確服務(wù)器期待客戶端進(jìn)行何種反應(yīng)。

303 See Other(查看其他)
對應(yīng)當(dāng)前請求的響應(yīng)可以在另一個URI上被找到,當(dāng)響應(yīng)于POST(或PUT / DELETE)接收到響應(yīng)時,客戶端應(yīng)該假定服務(wù)器已經(jīng)收到數(shù)據(jù),并且應(yīng)該使用單獨的GET消息發(fā)出重定向。
這個方法的存在主要是為了允許由腳本激活的POST請求輸出重定向到一個新的資源。這個新的URI不是原始資源的替代引用。
同時,303響應(yīng)禁止被緩存。當(dāng)然,第二個請求(重定向)可能被緩存。新的URI應(yīng)當(dāng)在響應(yīng)的Location域中返回。除非這是一個HEAD請求,否則響應(yīng)的實體中應(yīng)當(dāng)包含指向新的URI的超鏈接及簡短說明。注意:許多HTTP/1.1版以前的瀏覽器不能正確理解303狀態(tài)。如果需要考慮與這些瀏覽器之間的互動,302狀態(tài)碼應(yīng)該可以勝任,因為大多數(shù)的瀏覽器處理302響應(yīng)時的方式恰恰就是上述規(guī)范要求客戶端處理303響應(yīng)時應(yīng)當(dāng)做的。

307 Temporary Redirect(臨時重定向)
在這種情況下,請求應(yīng)該與另一個URI重復(fù),但后續(xù)的請求應(yīng)仍使用原始的URI。與302相反,當(dāng)重新發(fā)出原始請求時,不允許更改請求方法。例如,應(yīng)該使用另一個POST請求來重復(fù)POST請求

308 Permanent Redirect (永久重定向)
請求和所有將來的請求應(yīng)該使用另一個URI重復(fù)。307和308重復(fù)302和301的行為,但不允許HTTP方法更改。例如,將表單提交給永久重定向的資源可能會順利進(jìn)行。

301/302/303/307/308的區(qū)別
301,302是http1.0的內(nèi)容,303、307、308是http1.1的內(nèi)容。
301和302本來在規(guī)范中是不允許重定向時改變請求方法的(將POST改為GET),但是許多瀏覽器卻允許重定向時改變請求方法(這是一種不規(guī)范的實現(xiàn))。
303的出現(xiàn)正是為了給上面的301,302這種行為作出個規(guī)范(將錯就錯吧),也就是允許重定向時改變請求方法。此外303響應(yīng)禁止被緩存。
大多數(shù)的瀏覽器處理302響應(yīng)時的方式恰恰就是上述規(guī)范要求客戶端處理303響應(yīng)時應(yīng)當(dāng)做的,所以303基本用的很少,一般用302。
307和308的出現(xiàn)也是給上面的行為做個規(guī)范,不過是不允許重定向時改變請求方法。
Permanent | Temporary | |
Allows changing the request method from POST to GET. | 301 | 302 |
Does not allow changing the request method from POST to GET. | 308 | 307 |
注:永久(Permanent)和臨時(Temporary)的區(qū)別
永久是指原來訪問的資源已經(jīng)永久刪除啦,客戶端應(yīng)該根據(jù)新的URI訪問重定向。
臨時是指訪問的資源可能暫時先用location的URI訪問,但舊資源還在的,下次你再來訪問的時候可能就不用重定向了。
故301與302的區(qū)別:
301表示搜索引擎在抓取新內(nèi)容的同時也將舊的網(wǎng)址交換為重定向之后的網(wǎng)址;302表示舊地址A的資源還在(仍然可以訪問),這個重定向只是臨時地從舊地址A跳轉(zhuǎn)到地址B,搜索引擎會抓取新的內(nèi)容而保存舊的網(wǎng)址。
使用場景
因為301與302的區(qū)別,所以導(dǎo)致產(chǎn)生302網(wǎng)址劫持,故不建議使用302重定向(然而瀏覽器默認(rèn)是使用302重定向)
302 重定向和網(wǎng)址劫持(URL hijacking)
從網(wǎng)址A 做一個302 重定向到網(wǎng)址B 時,主機(jī)服務(wù)器的隱含意思是網(wǎng)址A 隨時有可能改主意,重新顯示本身的內(nèi)容或轉(zhuǎn)向其他的地方。大部分的搜索引擎在大部分情況下,當(dāng)收到302重定向時,一般只要去抓取目標(biāo)網(wǎng)址就可以了,也就是說網(wǎng)址B。如果搜索引擎在遇到302 轉(zhuǎn)向時,百分之百的都抓取目標(biāo)網(wǎng)址B 的話,就不用擔(dān)心網(wǎng)址URL 劫持了。問題就在于,有的時候搜索引擎,尤其是Google,并不能總是抓取目標(biāo)網(wǎng)址。比如說,有的時候A 網(wǎng)址很短,但是它做了一個302重定向到B網(wǎng)址,而B網(wǎng)址是一個很長的亂七八糟的URL網(wǎng)址,甚至還有可能包含一些問號之類的參數(shù)。很自然的,A網(wǎng)址更加用戶友好,而B網(wǎng)址既難看,又不用戶友好。這時Google很有可能會仍然顯示網(wǎng)址A。由于搜索引擎排名算法只是程序而不是人,在遇到302重定向的時候,并不能像人一樣的去準(zhǔn)確判定哪一個網(wǎng)址更適當(dāng),這就造成了網(wǎng)址URL劫持的可能性。也就是說,一個不道德的人在他自己的網(wǎng)址A做一個302重定向到你的網(wǎng)址B,出于某種原因, Google搜索結(jié)果所顯示的仍然是網(wǎng)址A,但是所用的網(wǎng)頁內(nèi)容卻是你的網(wǎng)址B上的內(nèi)容,這種情況就叫做網(wǎng)址URL 劫持。你辛辛苦苦所寫的內(nèi)容就這樣被別人偷走了。302重定向所造成的網(wǎng)址URL劫持現(xiàn)象,已經(jīng)存在一段時間了。不過到目前為止,似乎也沒有什么更好的解決方法。在正在進(jìn)行的谷歌大爸爸?jǐn)?shù)據(jù)中心轉(zhuǎn)換中,302 重定向問題也是要被解決的目標(biāo)之一。從一些搜索結(jié)果來看,網(wǎng)址劫持現(xiàn)象有所改善,但是并沒有完全解決。
使用301的場景:(一般是資源位置永久更改)
1.域名到期不想續(xù)費(或者發(fā)現(xiàn)了更適合網(wǎng)站的域名),想換個域名。
2.在搜索引擎的搜索結(jié)果中出現(xiàn)了不帶www的域名,而帶www的域名卻沒有收錄,這個時候可以用301重定向來告訴搜索引擎我們目標(biāo)的域名是哪一個。
3.空間服務(wù)器不穩(wěn)定,換空間的時候。
注:另外,返回301請求碼進(jìn)行跳轉(zhuǎn)被谷歌認(rèn)為是將網(wǎng)站地址由 HTTP 遷移到 HTTPS的最佳方法(然而大家都用302。。。。)
使用302的場景:(一般是普通的重定向需求:臨時跳轉(zhuǎn))
1.未登錄前先使用302重定向到登錄頁面,登錄成功后再跳回到原來請求的頁面
舉個例子,比如我未登錄京東前我就訪問京東的個人界面https://home.jd.com/,然后就會重定向到登錄界面,我們可以通過瀏覽器的dev-tool查看狀態(tài)碼,有

我們可以發(fā)現(xiàn)響應(yīng)的狀態(tài)碼為302,并且返回了location為登錄界面的url,并且附帶了ReturnUrl方便我們登錄后跳回到https://home.jd.com/
2.有時候需要自動刷新頁面,比如5秒后回到訂單詳細(xì)頁面之類。
例子略。
3.有時系統(tǒng)進(jìn)行升級或者切換某些功能時,需要臨時更換地址。
例子略。
4.像微博之類的使用短域名,用戶瀏覽后需要重定向到真實的地址之類。
例如我訪問一個微博的秒拍視頻鏈接:http://t.cn/RuUMBnI,然后重定向到了實際的視頻地址miaopai.com,狀態(tài)碼為302。

再來個例子,我訪問了另一個微博的秒拍視頻鏈接:http://t.cn/RuOcwxn,然后重定向了兩次,先是301重定向到video.weibo.com,再302重定向到miaopai.com。
第一次:

第二次:
· 
5.電腦端與移動端的轉(zhuǎn)換
比如我訪問網(wǎng)頁端頁面https://www.taobao.com/,302重定向到了移動端頁面m.taobao.com

使用303的場景
幾乎沒有,一般就是用302
使用307的場景
很少用,與302類似,只不過是針對POST方法的請求不允許更改方法
不過我在訪問百度時,發(fā)現(xiàn)用了307狀態(tài)碼

使用308的場景
很少用,與301類似,只不過是針對POST方法的請求不允許更改方法
轉(zhuǎn)載于:https://www.cnblogs.com/wuguanglin/p/redirect.html
