<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          搞懂 HTTP 重定向 - 如何優(yōu)雅地使用 301

          共 6198字,需瀏覽 13分鐘

           ·

          2021-02-20 13:34

          最近一段時(shí)間,連續(xù)遇到了兩次跟重定向相關(guān)的問題,本著知己知彼百戰(zhàn)百勝的態(tài)度,我決定深入了解一下,順便跟大家分享一下。

          關(guān)注?全棧前端精選,回復(fù)“1

          加入我們一起學(xué)習(xí),天天進(jìn)步

          作為前端開發(fā),大家對重定向一定不陌生,不就是永久重定向和臨時(shí)重定向嘛,誰還不知道呢 ??。

          那么大家是否知道永久重定向和臨時(shí)重定向的區(qū)別呢?如果不小心設(shè)置了永久重定向該如何取消呢?如何優(yōu)雅地使用重定向呢?接下來就讓我們來一探究竟吧。

          URL 重定向,能夠?qū)⒍鄠€(gè) URL 指向同一個(gè)頁面,這一技術(shù)有著多種用途。在 HTTP 中有一個(gè)專門的響應(yīng),叫做 HTTP 重定向,也就是所有 3 開頭的響應(yīng)(這個(gè)相信大家都背過)。

          除了 HTTP 重定向,還有其他方式能夠進(jìn)行重定向,本文也會介紹。

          內(nèi)容較長,我們先看一下本文的內(nèi)容架構(gòu):

          1. HTTP 重定向詳解
          2. 其他類型的重定向方式
          3. 重定向的使用場景
          4. 如何優(yōu)雅地使用 301

          1. HTTP 重定向

          在 HTTP 中,服務(wù)器可以通過返回一個(gè)重定向響應(yīng)來進(jìn)行重定向。這個(gè)重定向響應(yīng)有一個(gè)以 3 開頭的狀態(tài)碼 ,并且有一個(gè) Location 頭字段 表示要重定向到的位置。

          瀏覽器接收到這個(gè)重定向之后,會立即加載 Location 中指定的 URL。通常這一過程耗時(shí)極端,用戶基本注意不到這個(gè)過程。

          重定向過程如下圖所示:


          重定向過程


          1.1 重定向狀態(tài)碼及含義

          前面提到,重定向相關(guān)的狀態(tài)碼都是以 3 開頭的,主要有以下 9 種狀態(tài)碼:


          狀態(tài)碼狀態(tài)短語狀態(tài)含義
          300Multiple Choices當(dāng)請求的 URL 對應(yīng)有多個(gè)資源時(shí)(如同一個(gè) HTML 的不同語言的版本),返回這個(gè)代碼時(shí),可以返回一個(gè)可選列表,這樣用戶可以自行選擇。通過 Location 頭字段可以自定首選內(nèi)容。
          301Moved Permanetly當(dāng)前請求的資源已被移除時(shí)使用,響應(yīng)的 Location 頭字段會提供資源現(xiàn)在的 URL。直接使用 GET 方法發(fā)起新情求。
          302Found與 301 類似,但客戶端只應(yīng)該將 Location 返回的 URL 當(dāng)做臨時(shí)資源來使用,將來請求時(shí),還是用老的 URL。直接使用 GET 方法發(fā)起新情求。
          303See Other用于在 PUT 或者 POST 請求之后進(jìn)行重定向,這樣在結(jié)果頁就不會再次觸發(fā)重定向了。
          304Not Modified資源未修改,表示本地緩存仍然可用。
          305Use Proxy用來表示必須通過一個(gè)代理來訪問資源,代理的位置有 Location 頭字段給出
          306Switch Proxy在最新版的規(guī)范中,306 狀態(tài)碼已經(jīng)不再被使用。最初是指“后續(xù)請求應(yīng)使用指定的代理”。
          307Temporary Redirect與 302 類似,但是使用原請求方法發(fā)起新情求。
          308Permanent Redirect與 301 類似,但是使用原請求方法發(fā)起新情求。


          總共有 9 個(gè)與重定向相關(guān)的狀態(tài)碼,其中 301/302/304 都比較常見,305/306 使用較少,本文不做介紹(其實(shí)我也不懂,也沒用過 ??)。這 9 種狀態(tài)碼可以分成 3 大類,分別是:永久重定向、臨時(shí)重定向以及特殊重定向。

          1.2 永久重定向類

          301 和 308 都屬于永久重定向。永久重定向意味著原始 URL 不再可用,替換成了一個(gè)新的內(nèi)容。所以搜索引擎、聚合內(nèi)容閱讀器以及其他爬蟲識別這兩個(gè)狀態(tài)碼時(shí),會更新舊 URL 的資源。

          劃重點(diǎn):這個(gè)就是永久重定向和臨時(shí)重定向的區(qū)別。

          規(guī)范中,301 本來不允許改變請求方法,但是已有的瀏覽器廠商都使用了 GET 方法進(jìn)行新的請求。所以創(chuàng)建了 308 用來處理需要使用非 GET 進(jìn)行重定向的場景。

          1.3 臨時(shí)重定向類

          302/303/307 都屬于臨時(shí)重定向。有時(shí),當(dāng)原有資源因?yàn)橐恍┎豢深A(yù)測的原因而臨時(shí)無法訪問時(shí),可以通過臨時(shí)重定向的方式將請求轉(zhuǎn)移到另一個(gè)地方。搜索引擎和爬蟲不應(yīng)該記住這個(gè)臨時(shí)的連接。

          此外,臨時(shí)重定向還可以用來在創(chuàng)建、修改和刪除時(shí)展示臨時(shí)的進(jìn)度頁,這里通常使用 303。

          302 和 307 的關(guān)系類似于 301 和 308,參見上文。

          1.4 特殊重定向類

          除此之外,300/304/305/306 可以歸屬到特殊重定向類。這里重點(diǎn)說一下 304,304 是 HTTP 緩存中的一個(gè)重要內(nèi)容,表示資源未修改,相當(dāng)于將資源重定向到本地緩存。

          關(guān)于 HTTP 緩存的詳細(xì)內(nèi)容,可以查看這篇文章:瀏覽器緩存策略之掃盲篇

          2. 其他類型的重定向方式

          HTTP 是最簡易使用的重定向方式,但是有些時(shí)候我們并不能夠操作服務(wù)端。好在,除了 HTTP 重定向外,還有兩種方式:通過進(jìn)行 HTML 重定向和通過 DOM 的 JS 重定向。

          2.1 HTML 重定向

          如下代碼所示,我們可以通過在元素上設(shè)置http-equiv="Refresh可以實(shí)現(xiàn)頁面的重定向。


          ??"Refresh"?content="0;?URL=https://example.com/">

          復(fù)制代碼

          content屬性需要以數(shù)字開頭,表示多少秒之后重定向到指定頁面。通常我們設(shè)置為 0。

          注意,這一方式只適用于 HTML

          2.2 JavaScript 重定向

          這個(gè)大家都用過,使用window.location可以重定向頁面。這個(gè)方法很常見,不過多做介紹。

          當(dāng)然,這一方式只在 JavaScript 的客戶端執(zhí)行環(huán)境有效。

          上述所介紹的三種重定向方式中,按照優(yōu)先級順序如下:HTTP > HTML > JavaScript。這和我們所知道的文件的請求處理順序一致,不過多解釋。

          3. 重定向的使用場景

          不同類別的重定向有不同的使用場景,大致可以分為以下幾類:

          • 網(wǎng)站別名:通常情況下,對于一個(gè)資源,我們只有一個(gè) URL,但有些特殊情況下,資源會存在多個(gè) URL,這個(gè)時(shí)候就需要用到重定向。
            • 提高網(wǎng)站的可達(dá)率:比如 www.example.comexample.com都可以訪問到指定網(wǎng)站。
            • 遷移到新的站點(diǎn):因?yàn)槟承┰蚺f站點(diǎn)被廢棄,但仍然希望之前已經(jīng)存在的連接和收藏書簽?zāi)軌蛏?,這是可以使用重定向。
            • 強(qiáng)制跳轉(zhuǎn) HTTPS:當(dāng)我們的網(wǎng)站支持 HTTPS 時(shí),通常會強(qiáng)制使用 HTTPS,所以訪問 HTTP 時(shí)需要做重定向跳轉(zhuǎn)。
          • 保證已有鏈接可用:站點(diǎn)的維護(hù)是一個(gè)長時(shí)間的過程,有時(shí),我們在進(jìn)行重構(gòu)時(shí),會對一些鏈接或路由進(jìn)行調(diào)整,這時(shí)候我們內(nèi)部的 URL 可以修改,但是對于已在被外部引用了的鏈接卻無法修改。為了保證這部分的鏈接可用,我們通常需要設(shè)置重定向。
          • 對于危險(xiǎn)操作進(jìn)行重定向:類似編輯刪除等危險(xiǎn)操作,為了避免用戶刷新時(shí)重復(fù)觸發(fā)危險(xiǎn)操作,我們可以將其重定向到臨時(shí)的進(jìn)度展示頁,比如使用 303。對于耗時(shí)較長的請求也可以這么處理。

          4. 如何優(yōu)雅地使用 301

          有些時(shí)候,我們對于永久重定向的理解并不夠,在倉促之中使用了 301 永久重定向時(shí)就會遇到這樣的一個(gè)坑,那就是不管我們怎么重新設(shè)置,(有些)瀏覽器都仍然使用最開始設(shè)置的 301 永久重定向。

          這時(shí),我們的用戶甚至是我們自己的狀態(tài)大概是這樣的:

          網(wǎng)站:忍法 - 永久重定向之術(shù) 用戶&我們:我是誰?我在哪?我該怎么回去?

          往往在錯(cuò)誤配置了 301 之后,我們需要面臨的問題就是取消最初的 301?

          然而,很不幸的是,似乎并沒有好的辦法能夠快速的清除用戶端已經(jīng)使用過的錯(cuò)誤 301 重定向。

          如果用戶足夠聰明的話,還可以讓用戶按照我們的說明進(jìn)行處理。

          所以最好的做法是能夠搞懂并優(yōu)雅地使用 301,這樣才能避免這一問題。

          下面,我們先來復(fù)現(xiàn)問題,然后再解釋問題。

          4.1 準(zhǔn)備:使用 Nginx 配置 301 永久重定向

          在 Nginx 中,我們可以創(chuàng)建一個(gè) server 塊來指定所有內(nèi)容都進(jìn)行重定向:

          server?{
          ?listen?80;
          ?server_name?example.com;
          ?return?301?$scheme://www.example.com$request_uri;
          }
          復(fù)制代碼

          也可以通過rewrite指令指定目錄和頁面進(jìn)行重定向:

          rewrite?^/images/(.*)$?https://images.example.com/$1?redirect;
          rewrite?^/images/(.*)$?https://images.example.com/$1?permanent;
          復(fù)制代碼

          對于其他 web 服務(wù)器,可以參考 MDN 或者網(wǎng)上的其他教程進(jìn)行配置。

          比如我準(zhǔn)備了下面這樣一個(gè) nginx.conf 文件。

          server?{
          ??listen?80;
          ??server_name?redirect.example.com;
          ??root?/your-path/web-redirect;

          ??location?/original-page?{
          ????#?下面是兩種重定向方式,為了測試使用,啟用一個(gè)即可
          ????#?永久重定向
          ????rewrite?^/original-page?http://redirect.example.com/301?permanent;
          ????#?#?臨時(shí)重定向
          ????#?rewrite?^/original-page?http://redirect.example.com/302?redirect;
          ??}

          ??location?/301?{
          ????try_files?$uri?/301.html$is_args$args;
          ??}

          ??location?/302?{
          ????try_files?$uri?/302.html$is_args$args;
          ??}
          }
          復(fù)制代碼

          301.html/302.html 自行準(zhǔn)備即可,內(nèi)容自己能區(qū)分出來就行。

          現(xiàn)在我們假設(shè)不小心將初始頁面永久重定向到了 301 頁面,現(xiàn)在想取消這一行為,臨時(shí)重定向到 302 頁面。

          1. 先開啟永久重定向的規(guī)則,在瀏覽器訪問http://redirect.example.com/original-page,會發(fā)現(xiàn)重定向到了 301。
          2. 關(guān)閉永久重定向規(guī)則,開啟臨時(shí)重定向,再次訪問初始頁面,看看是否重定向到了 302 頁面。

          至此,我們會發(fā)現(xiàn),301 之后,瀏覽器會記住第一次的 301,忽略之后的其他重定向。那這樣到底是為什么呢?

          4.2 瀏覽器會緩存“301”永久重定向

          這所以會這樣,這是因?yàn)闉g覽器會緩存“301”永久重定向。

          經(jīng)不完全測試,各瀏覽器的緩存情況如下:



          是否緩存重啟是否清除時(shí)間改為 1 年后是否失效5 年后
          Chrome未清除未失效未失效
          FireFox未清除未失效未失效
          Safari清除失效失效
          IE--(沒測)------


          可以看出除了 Safari 重啟/修改時(shí)間之后,能夠使用新的重定向,Chrome/Firefox 都會無限期的緩存 301 重定向。

          在 FireFox 中我們也可以簡單驗(yàn)證下,輸入about:cache,在磁盤緩存中可以找到相關(guān)的緩存項(xiàng)。如下:


          FireFox中的301緩存內(nèi)容


          瀏覽器為什么會緩存 301 重定向呢?其實(shí),HTTP RFC 中規(guī)定 301 是一個(gè)可緩存的響應(yīng),所以瀏覽器會根據(jù)響應(yīng)中的 HTTP 緩存頭進(jìn)行緩存。如果我們沒有提供明確的緩存頭,瀏覽器就會默認(rèn)永久緩存 301 響應(yīng),因?yàn)?301 是永久重定向的意思。

          這里筆者偷懶沒有測試 IE,但是鑒于有瀏覽器(Chrome/Firefox)會無限期緩存 301 重定向,那么我們就需要試著去解決這一問題 —— 如何清除 301 重定向緩存。

          4.3 如何清除 301 重定向緩存

          內(nèi)心戲:不是說沒法清除嗎?這怎么介紹了。我:別急,先看完。

          既然是緩存行為,那么我們就可以通過常規(guī)的緩存清理方式來處理,包括但不限于以下幾種方式:

          • 控制臺禁用緩存
          • 清除歷史記錄
          • Network 面板清除緩存

          這里大家可以自行嘗試以下,如果不行的話,記得多試 1-2 遍就行(至于為什么要多試,我也很奇怪,有的時(shí)候就是清兩遍就好了)。

          如果大家驗(yàn)證了上面的幾種清除方式,就會發(fā)現(xiàn)確實(shí)是行之有效的。那為什么我會說沒有很好地方式去清除呢?

          大家細(xì)想,當(dāng)我們將錯(cuò)誤的 301 請求發(fā)布到線上環(huán)境了,并且影響了數(shù)以萬計(jì)的用戶時(shí),我們要怎么通知并教會用戶按照我們的方式去清除緩存呢?當(dāng)然,清除歷史記錄算是最便捷的方式了,如果真的不行遇到了這種情況,那就通知用戶這么清除吧 ??。

          4.4 優(yōu)雅地使用 301

          為了避免上面需要清除的情況,最好的做法是優(yōu)雅地使用 301。

          前面解釋瀏覽器為什么會緩存 301 重定向時(shí),已經(jīng)隱晦地提到了這一方法。

          既然瀏覽器認(rèn)為這是一個(gè)可以緩存的資源,并且我們可以通過緩存頭來控制。那么在使用 301 時(shí),我們將其設(shè)置為不緩存就可以了。比如設(shè)置 Cache-Control: no-storeCache-Control: no-cache。

          location?/original-page?{
          +?add_header?Cache-Control?no-store;
          ??#?永久重定向
          ??rewrite?^/original-page?http://redirect.example.com/301?permanent;
          ??#?臨時(shí)重定向
          ??#?rewrite?^/original-page?http://redirect.example.com/302?redirect;
          }
          復(fù)制代碼

          這樣設(shè)置之后,如果我們再將重定向切換成 302,會發(fā)現(xiàn)瀏覽器不會緩存 301 了,新的重定向可以立即生效了。

          總結(jié)

          以上就是重定向相關(guān)的內(nèi)容。301 使用需謹(jǐn)慎,一定要設(shè)緩存頭 ??。


          參考資料

          [1]

          維基百科 - HTTP 狀態(tài)碼:?https://zh.wikipedia.org/wiki/HTTP%E7%8A%B6%E6%80%81%E7%A0%81

          [2]

          MDN - Redirections in HTTP:?https://developer.mozilla.org/en-US/docs/Web/HTTP/Redirections

          [3]

          瀏覽器將 HTTP 301 緩存多長時(shí)間?:?https://qastack.cn/programming/9130422/how-long-do-browsers-cache-http-301s

          [4]

          瀏覽器對 301 重定向的緩存:?https://juejin.cn/post/6844904045614743560

          [5]

          Chromium - Feature Request: I need a way to clear the 301 redirect cache:?https://bugs.chromium.org/p/chromium/issues/detail?id=633023&can=1&q=clear%20301%20redirects&colspec=ID%20Pri%20M%20Stars%20ReleaseBlock%20Component%20Status%20Owner%20Summary%20OS%20Modified

          瀏覽 76
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  色色色色综合网 | 亚洲天堂2014 | 久久激情五月天 | 无码对白 | 精品xxxxx |