HTTP 中的重定向
URL 重定向,也稱為URL 轉發,是一種為頁面、表單、整個網站或 Web 應用程式提供多個 URL 地址的技術。HTTP 為此操作提供了一種特殊的響應,稱為 HTTP 重定向。
重定向可實現眾多目標
- 網站維護或停機期間的臨時重定向
- 更改網站 URL 後,為保留現有連結/書籤的永久重定向;上傳檔案時的進度頁面等。
原理
在 HTTP 中,重定向是由伺服器向請求傳送特殊的重定向響應觸發的。重定向響應具有以 3 開頭的狀態碼和包含要重定向到的 URL 的 Location 標頭。
當瀏覽器收到重定向時,它們會立即載入 Location 標頭中提供的新 URL。除了額外的往返帶來的少量效能損失外,使用者很少會注意到重定向。
重定向有多種型別,分為三類
永久重定向
這些重定向旨在永久有效。它們意味著原始 URL 不應再使用,並被新 URL 替換。搜尋引擎機器人、RSS 閱讀器和其他爬蟲會更新資源的原始 URL。
| 程式碼 | 文字 | 方法處理 | 典型用例 |
|---|---|---|---|
301 |
永久移動 |
GET 方法不變。其他方法可能會或可能不會更改為 GET。[1] |
網站重組。 |
308 |
永久重定向 |
方法和正文不變。 | 網站重組,包含非 GET 連結/操作。 |
[1] 規範無意允許方法更改,但現有使用者代理確實會更改其方法。308 的建立是為了消除使用非 GET 方法時行為的模糊性。
臨時重定向
有時無法從其規範位置訪問請求的資源,但可以從其他位置訪問。在這種情況下,可以使用臨時重定向。
搜尋引擎機器人和其他爬蟲不會記住新的臨時 URL。臨時重定向也用於建立、更新或刪除資源時,以顯示臨時進度頁面。
| 程式碼 | 文字 | 方法處理 | 典型用例 |
|---|---|---|---|
302 |
已找到 |
GET 方法不變。其他方法可能會或可能不會更改為 GET。[2] |
Web 頁面因不可預見的原因暫時不可用。 |
303 |
檢視其他 |
GET 方法不變。其他方法更改為 GET(正文丟失)。 |
在 PUT 或 POST 後用於重定向,這樣重新整理結果頁面就不會重新觸發操作。 |
307 |
臨時重定向 |
方法和正文不變 | Web 頁面因不可預見的原因暫時不可用。當網站上存在非 GET 操作時,比 302 更好。 |
[2] 規範無意允許方法更改,但現有使用者代理確實會更改其方法。307 的建立是為了消除使用非 GET 方法時行為的模糊性。
特殊重定向
304(未修改)將頁面重定向到本地快取的副本(已過期),而 300(多項選擇)是手動重定向:瀏覽器以網頁形式顯示的正文列出了可能的重定向,使用者點選其中一個進行選擇。
| 程式碼 | 文字 | 典型用例 |
|---|---|---|
300 |
多項選擇 |
不多:選項在正文中的 HTML 頁面中列出。鼓勵將機器可讀的選項作為帶有 rel=alternate 的 Link 標頭髮送。 |
304 |
未修改 |
針對重新驗證的條件請求傳送。指示快取的響應仍然有效且可以使用。 |
指定重定向的替代方式
HTTP 重定向不是定義重定向的唯一方式。還有另外兩種方式
HTML 重定向
HTTP 重定向是建立重定向的最佳方式,但有時您無法控制伺服器。在這種情況下,請嘗試在頁面的 <head> 中使用 <meta> 元素,並將其 http-equiv 屬性設定為 Refresh。顯示頁面時,瀏覽器將轉到指示的 URL。
<head>
<meta http-equiv="Refresh" content="0; URL=https://example.com/" />
</head>
content 屬性應以一個數字開頭,指示瀏覽器在重定向到給定 URL 之前應等待多少秒。為了符合輔助功能要求,始終將其設定為 0。
顯然,此方法僅適用於 HTML,不能用於影像或其他型別的內容。
JavaScript 重定向
JavaScript 中的重定向透過將 URL 字串設定為 window.location 屬性來執行,從而載入新頁面
window.location = "https://example.com/";
與 HTML 重定向一樣,這不能對所有資源都有效,而且顯然,這隻適用於執行 JavaScript 的客戶端。另一方面,有更多可能性:例如,您可以僅在滿足某些條件時觸發重定向。
優先順序
有三種觸發重定向的方式,可以同時使用多種方式。但哪個先應用?
- HTTP 重定向總是首先執行——它們甚至在沒有傳輸頁面時就存在了。
- 有點令人驚訝的是,JavaScript 重定向在 HTML 重定向之前執行。這是因為
<meta>重定向發生在頁面完全載入之後,也就是所有指令碼執行之後。 - 如果頁面載入之前沒有執行任何 HTTP 重定向或 JavaScript 重定向,則執行 HTML 重定向(
<meta>)。 - 如果在頁面載入後發生任何 JavaScript 重定向(例如,點選按鈕時),如果頁面尚未被先前的方法重定向,它將最後執行。
如果可能,請使用 HTTP 重定向,不要新增 <meta> 元素重定向。如果有人更改了 HTTP 重定向但忘記更改 HTML 重定向,重定向將不再相同,這可能導致無限迴圈或其他噩夢。
用例
重定向有許多用例,但由於每次重定向都會影響效能,因此應將其使用降至最低。
域名別名
理想情況下,每個資源都有一個位置,因此有一個 URL。但資源有替代名稱的原因
- 擴大您網站的覆蓋範圍
-
一個常見的情況是,網站位於
www.example.com,但從example.com訪問也應該有效。因此,會設定將example.com重定向到www.example.com。您還可以從您的域名的常見同義詞或常見拼寫錯誤進行重定向。 - 遷移到新域名
-
例如,您的公司改名了,但您希望現有連結或書籤仍然可以透過新名稱找到您。
- 強制 HTTPS
-
對您網站的
http://版本的請求將重定向到您網站的https://版本。
保持連結有效
重構網站時,URL 會更改。即使您更新網站連結以匹配新 URL,您也無法控制外部資源使用的 URL。
您不想破壞這些連結,因為它們會帶來有價值的使用者並幫助您的 SEO,因此您會設定從舊 URL 到新 URL 的重定向。
注意:此技術適用於內部連結,但儘量避免內部重定向。重定向會產生顯著的效能成本(因為會發生額外的 HTTP 請求)。如果您可以透過糾正內部連結來避免它,您應該修復這些連結。
對不安全請求的臨時響應
不安全的請求會修改伺服器的狀態,使用者不應無意中重新發送它們。
通常,您不希望使用者重新發送 PUT、POST 或 DELETE 請求。如果您將此請求的結果作為響應提供,則按重新載入按鈕將重新發送請求(可能在確認訊息之後)。
在這種情況下,伺服器可以針對包含正確資訊的 URL 發回 303(檢視其他)響應。如果按下重新載入按鈕,只會重新顯示該頁面,而不會重播不安全的請求。
對長時間請求的臨時響應
某些請求可能需要在伺服器上花費更多時間,例如計劃稍後處理的 DELETE 請求。在這種情況下,響應是 303(檢視其他)重定向,該重定向連結到一個頁面,指示操作已安排,並最終通知其進度或允許取消它。
在常用伺服器中配置重定向
Apache
重定向可以在伺服器配置檔案或每個目錄的 .htaccess 中設定。
mod_alias 模組具有 Redirect 和 RedirectMatch 指令,預設情況下會設定 302 重定向
<VirtualHost *:443>
ServerName example.com
Redirect / https://www.example.com
</VirtualHost>
URL https://example.com/ 將重定向到 https://www.example.com/,其下的任何檔案或目錄也將重定向(https://example.com/some-page 將重定向到 https://www.example.com/some-page)
RedirectMatch 作用相同,但接受正則表示式來定義受影響的 URL 集合
RedirectMatch ^/images/(.*)$ https://images.example.com/$1
images/ 目錄中的所有文件都將重定向到不同的域。
如果您不想要臨時重定向,可以使用額外的引數(要使用的 HTTP 狀態碼或 permanent 關鍵字)來設定不同的重定向
Redirect permanent / https://www.example.com
# …acts the same as:
Redirect 301 / https://www.example.com
mod_rewrite 模組也可以建立重定向。它更靈活,但也更復雜一些。
Nginx
在 Nginx 中,您為要重定向的內容建立一個特定的伺服器塊
server {
listen 80;
server_name example.com;
return 301 $scheme://www.example.com$request_uri;
}
要將重定向應用於目錄或僅某些頁面,請使用 rewrite 指令
rewrite ^/images/(.*)$ https://images.example.com/$1 redirect;
rewrite ^/images/(.*)$ https://images.example.com/$1 permanent;
IIS
在 IIS 中,您使用 <httpRedirect> 元素來配置重定向。
重定向迴圈
重定向迴圈發生在已跟蹤的重定向之後又出現額外重定向時。換句話說,存在一個永遠不會結束的迴圈,並且永遠找不到頁面。
大多數情況下,這是一個伺服器問題,如果伺服器能夠檢測到它,它會返回 500 Internal Server Error。如果您在修改伺服器配置後不久遇到此類錯誤,則很可能是重定向迴圈。
有時,伺服器不會檢測到它:重定向迴圈可能跨越多個伺服器,每個伺服器都沒有完整的檢視。在這種情況下,瀏覽器會檢測到它並顯示錯誤訊息。Firefox 顯示
Firefox 檢測到伺服器以一種永遠不會終止的方式重定向此地址的請求。
……而 Chrome 顯示
此網頁存在重定向迴圈
在這兩種情況下,使用者都無能為力(除非他們一方發生損壞,例如快取或 Cookie 不匹配)。
避免重定向迴圈很重要,因為它們會完全破壞使用者體驗。
另見
- 3XX 重定向響應狀態
Location標頭- 用於使用 JavaScript 進行重定向的
window.location屬性