net/http 包主要提供 HTTP 相關的服務,可以使用這個包開發一個 webapp 的服務端。
如果你是一個后端開發人員的話,可能你常常會使用類似 Postman 這種類型的工具來發送 HTTP 請求來測試后端接口,其實這個功能在 PyCharm 中就可以直接完成,只需要安裝 Http Client 插件即可。顯示下面的頁面,輸入相應的url,path 及相關參數:執行后,點擊 Response 可以看到返回結果:Tips:這個插件還支持一次運行多個請求(Open HTTP Requests Collection),也能像 Postman 一樣查看歷史請求。
Http 是一種協議,它制定了瀏覽器客戶端和 Web 服務端信息傳遞的規則,所有的瀏覽器廠商和所有的 Web 后臺服務都是遵從這個規則來實現信息的傳遞的。Web 服務的信息傳遞從最早期單一的文字,到后來有了圖片,音頻視頻,而 HTTP 協議隨著傳遞信息的變化也經歷了以下幾個版本的變化:HTTP/0.9:于 1990 年問世,用于簡單文字的交換;HTTP/1.0:被正式列為 www 傳輸的標準,納入 RFC1945;HTTP/1.1:在 1.0 的基礎上新增了連接方式的規約;HTTP/2.0:隨著網絡的應用越來越廣,內容也越來越豐富。HTTP2.0 在安全,性能,交互場景都有了很大的改進。目前市場上主流的還是 HTTP/1.1 ,隨便打開一個瀏覽器 F12 查看下網絡,基本上都可以看到 版本:HTTP/1.1。但是 HTTP/2.0 作為下一代的網絡協議,前景可期。因為我們現在的網絡都在追求加速,在硬件不斷疊加,程序不斷優化,CDN資源加速,之后如果繼續優化的話那就只有 HTTP 協議本身了。2.0 因為有了多路復用,協議壓縮等功能,所以性能上面是要比 1.1 高出不少的,普及只是時間問題。
Syntax: http { ... }Default: —Context: main可以看到 http 指令是指令塊形式,屬于主環境 main,它里面的指令是用于設置 http 相關參數的。比如設置 server 配置等,配置連接超時時間等。...# 主位置,最左邊http { #指令或者指令塊 ...} ...
** 面試官提問:** 為什么有了 HTTP 協議后還出現了 HTTPS 協議?HTTPS 協議解決了什么問題?題目解析:在研究 HTTPS 協議之前,我們先總結下 HTTP 協議的優點和缺點:優點缺點通信方式簡單:基于請求和響應,客戶端發起請求,服務器端返回響應明文通信:信息明文傳輸,安全性低。無需維護狀態:HTTP 是無狀態協議,不識別客戶端。沒有狀態:例如對于需要保持登錄狀態的網站,需要依靠其他外部方式(Cookie、Session)維護狀態。速度快,效率高。如上表所示,HTTP 協議犧牲了安全性,換來了效率,但是在某些安全性要求高的場景,使用 HTTP 協議是不合適的。HTTP 協議的全稱是 Hypertext Transfer Protocol,HTTPS 協議的全程是 Hypertext Transfer Protocol Secure,多了一個 Secure(安全)的限制詞。從協議上看,HTTPS 協議基于 HTTP 協議,使用 SSL/TLS 協議對傳輸內容進行加密,從公式上定義:HTTP + SSL(TLS) = HTTPS。HTTPS 協議將 HTTP 協議的通信部分由 SSL 或者 TLS 協議替代,網絡模型劃分如下:? (HTTP 和 HTTPS 模型圖) 除了 SSL 協議以外,HTTPS 協議還涉及幾個重要的概念:CA 證書、混淆加密方式,以及 HTTPS 協議具體的工作流程,下面我們拆分解釋。
在 HTTP 請求頭里有個 Referer 字段,用于表明請求的來源地址。以向銀行發出轉賬請求為例,說明 Referer 字段。1. 用戶正常發出轉賬請求用戶登錄銀行網站成功后,在網站首頁 http://www.bank.com/,存在一個轉賬按鈕;用戶通過點擊頁面上的轉賬按鈕進行轉賬,向銀行發出轉賬請求 http://www.bank.com/transfer,該請求的信息如下:屬性描述請求的地址 http://www.bank.com/transfer 請求的 Refererhttp://www.bank.com/可以看出:請求的地址和請求的 Referer 是屬于相同的域名。2. 攻擊者通過 CSRF 攻擊發出轉賬請求如果用戶被誘導進入惡意網站 http://www.malicious.com,在惡意網站的頁面中向銀行發起轉賬請求,請求的屬性如下:屬性描述請求的地址 http://www.bank.com/transfer 請求的 Refererhttp://www.malicious.com/可以看出:請求的地址和請求的 Referer 是屬于不同的域名。
面試官提問: 什么是 HTTP 報文?什么是 HTTP 報文?題目解析: 首先,我們給出 HTTP 的定義:HTTP(HyperText Transfer Protocol,超文本傳輸協議)是一個請求 - 響應(Request to Response)協議,位于網絡模型的應用層,基于傳輸層的 TCP 協議。? (HTTP 請求 - 響應模型)其次,HTTP 報文是在客戶端和服務器端傳輸的數據報文,由起始行(Start Line)、請求頭部(Request Header)和請求主體(Request Body)構成,從類型上分為請求報文(Request Message)和響應報文(Response Message)。 (HTTP 報文格式)
nginx 七層方向代理處理的是 http 請求,對應的是 http 協議。如果只是轉發 http 請求,可以簡單使用 proxy_pass 指令即可。這和我們之前簡單的反向代理示例一致。# 在轉發 http 請求時,URL必須以 http 或者 https 開頭 Syntax: proxy_pass URL;Default: —Context: location, if in location, limit_except在使用 prxoy_pass 指令對 http 或者 https 協議進行反向代理時,需要注意一下問題:在 URL 不攜帶 URI 時,會將對應的 URL 直接轉發到上游服務器在 URL 攜帶 URI 時,會將 location 參數中匹配上的那一段替換為該URL看下面的示例配置:...http { server { listen 8000; location /test { proxy_pass http://ip:port/xyz; } } server { listen 9000; location /test { proxy_pass http://ip:port; } } }... 在代理 http 請求 http://主機ip:8000/test/abc 時,由于 proxy_pass 指令后面的 URL 帶了 /xyz 這樣的路徑,所以轉發的請求是 http:// ip:port/xyz/abc,其中匹配的 /test 已經被替換掉了。而對于第二個 http 請求 http://主機ip:9000/test/abc 時,由于 proxy_pass指令后面直接是上游服務器地址,沒有帶 URI,所以轉發的請求為 http://ip:port/test/abc,其中匹配到的/test并沒有被替換。
HTTP 協議,即超文本傳輸協議,是一個客戶端終端(用戶)和服務器端(網站)請求和應答的標準。這也是 Web 開發基礎。因為大部分網站或者 Web 服務的前后端交互幾乎都是走 HTTP 請求。HTTP 協議定義 Web 客戶端如何從 Web 服務器請求 Web 頁面,以及服務器如何把 Web 頁面傳送給客戶端。HTTP 協議采用了請求 / 響應模型??蛻舳讼蚍掌靼l送一個請求報文,請求報文包含請求的方法、URL、協議版本、請求頭部和請求數據。服務器以一個狀態行作為響應,響應的內容包括協議的版本、成功或者錯誤代碼、服務器信息、響應頭部和響應數據。HTTP 協議有如下特點:簡單快速:客戶向服務器請求服務時,只需傳送請求方法和路徑。由于 HTTP 協議簡單,使得 HTTP 服務器的程序規模小,因而通信速度很快;靈活:HTTP 允許傳輸任意類型的數據對象;無連接:無連接的含義是限制每次連接只處理一個請求。服務器處理完客戶的請求,并收到客戶的應答后,即斷開連接。采用這種方式可以節省傳輸時間;無狀態:HTTP 協議是無狀態協議。無狀態是指協議對于事務處理沒有記憶能力。缺少狀態意味著如果后續處理需要前面的信息,則它必須重傳,這樣可能導致每次連接傳送的數據量增大。另一方面,在服務器不需要先前信息時它的應答就較快。1.1.1 HTTP 常見請求在 HTTP/1.1 協議中共定義了八種方法(也叫 “動作”)來以不同方式操作指定的資源,目前我們比較常見和常用的有以下四個:GET 請求:向指定的資源發出 “顯示 “請求。使用 GET 方法應該只用在讀取數據,而不應當被用于產生 “副作用” 的操作中。一般在瀏覽器中直接敲擊 URL 并按回車鍵是執行的 GET 請求;POST 請求:向指定資源提交數據進行處理請求(例如提交表單或者上傳文件)。數據被包含在請求體中。POST 請求可能會導致新的資源的建立和 / 或已有資源的修改;PUT 請求:從客戶端向服務器傳送的數據取代指定的文檔的內容;DELETE 請求:請求服務器刪除指定的頁面。這四種請求和數據的增刪改查(CRUD) 可以看成是相對應的,一般在設計 URL 接口時,也會默認使用這樣特性,讓 GET 請求對應查詢數據、POST 請求對應數據的新增等等,這樣的接口設計出來才會具備良好的 Restful 風格。1.1.2 HTTP 狀態碼HTTP 請求通常會返回一個狀態碼,常見的 HTTP 狀態碼有:2xx:正確類。表示用戶請求被正確接收、理解和處理;200 - 請求成功;3xx:重定向類。表示沒有請求成功,必須采取進一步的動作;301 - 資源(網頁等)被永久轉移到其它 URL;302 - 資源臨時移動,資源只是臨時被移動,客戶端應繼續使用原有 URI ;4xx:客戶端錯誤。表示客戶端提交的請求包含語法錯誤或不能正確執行;400 - 往往是 Bad Request 錯誤。是指請求的方法不對;401 - 用戶沒有訪問權限,需要進行身份認證;403 - 禁止訪問;404 - 資源不存在,Not Found 錯誤;5xx:服務端錯誤。一般是說明服務器出現了問題;503 - 服務端錯誤,一般是服務器內部處理異常。實操: 用 curl 命令模擬發送 HTTP 請求。[root@server ~]# curl -I -XGET http://www.baidu.com/index.htmlHTTP/1.1 200 OKAccept-Ranges: bytesCache-Control: private, no-cache, no-store, proxy-revalidate, no-transformConnection: keep-aliveContent-Length: 2381Content-Type: text/htmlDate: Sun, 08 Mar 2020 14:36:01 GMTEtag: "588604c8-94d"Last-Modified: Mon, 23 Jan 2017 13:27:36 GMTPragma: no-cacheServer: bfe/1.0.8.18Set-Cookie: BDORZ=27315; max-age=86400; domain=.baidu.com; path=/
Http 協議除了我們的請求和響應參數,還包含了很多首部字段,這些字段使 Http 在滿足基本接口的請求接收參數之余,還有更多高級豐富的擴展。這些首部字段可以分為3類:通用首部字段 / 請求首部字段 / 響應首部字段。本節我們將學習的是通用首部字段。Http 報文結構
TCP 三次握手之后,客戶端和服務器端成功建立了連接,之后瀏覽器會向服務器特定端口發送HTTP請求。(https://imooc.com URL的請求報文)以 Chrome 瀏覽器為例,按下 F12 即可進入開發者模式,Network 一欄查看HTTP請求的具體報文。一個 HTTP 報文由請求行(Request Line)、請求頭部(Request Headers)、空行(Blank Line)以及請求體(Request Body)構成,請求行中規定了請求方法、URI 以及 HTTP 的版本,關于每個字段的詳細解釋,之前的小節已經進行了闡述。
HTTP 是我們進行爬蟲的一個基礎之一,我們通過 HTTT 協議才能順利爬取到 HTML 里面的內容,HTTP 相當于是一條道路,HTML 等網頁是道路的終點,我們必須遵守 HTTP 的交通規則,才能高效的在這條道路上運輸數據。
通常我們訪問網站的時候是直接輸入域名,比如:mybank.example.com,此時默認情況下瀏覽器會訪問 http://mybank.example.com。HTTP 協議由于信息不加密,無法保證訪問目標的真實性,容易受到中間人攻擊。增加 Strict-Transport-Security 響應頭,可以強制將訪問協議轉換成 Https。
HTTP 協議是一個簡單的請求-響應協議,它指定了客戶端可能發送給服務器什么樣的消息以及得到什么樣的響應。請求和響應消息的頭以 ASCII 碼形式給出;而消息內容則具有一個類似 MIME 的格式。瀏覽器向 Web 服務器發出請求時,它向服務器傳遞了一個請求信息,HTTP 請求信息由 3 部分組成:請求行;請求頭;請求正文。以下是一個 HTTP 請求消息的例子:GET / HTTP/1.1Host: www.xianlaiwan.cnConnection: keep-aliveUser-Agent: Mozilla/5.0 AppleWebKit/537.36 Chrome/81.0Accept: text/html,application/xml;image/webp,image/png,*/*;...省略...第一行是請求行,用來說明請求方法,要訪問的資源,以及所使用的 HTTP 版本。在這個例子中,請求方法是 GET,要訪問的資源是 /,HTTP 版本是 1.1,表示要獲取網站首頁 / 的內容。緊接著請求行之后的部分是請求頭部,用來說明服務器要使用的附加信息。例如:Host 指出請求的主機名,這里是 www.xianlaiwan.cn。請求頭部之后是請求正文,在請求正文中可以添加任意的其他數據,這個例子的請求正文為空。
服務器不支持請求中所指明的HTTP版本。
上一個小節中我們創建了第一個 Flask 程序,并且在瀏覽器中成功看到了 Flask 程序給我們返回的 Hello World。但是你有沒有注意到,我們看到的內容只是在后臺進行寫死的,也就是說無論你怎么請求,看到的永遠是 Hello World,無法根據自己的需求讓 Flask 程序返回給你想要的內容?這該怎么辦呢?不要急,我們有 HTTP 協議,HTTP 協議提供了多種方法訪問服務端資源,本小節講解常用的 HTTP 方法。并通過一個個具體的例子,說明如何在 Flask 中使用不同的 HTTP 方法。Tips:本節課所有代碼已經上傳到了 Github,可以點擊這里進行下載。
在你瀏覽互聯網的時候,絕大多數的數據都是通過 HTTP 協議獲取到的,也就是說如果你想要實現一個能上網的 App,那么就一定會和 HTTP 打上交道。當然 Android 發展到現在這么多年,已經有很多非常好用,功能非常完善的網絡框架了,比如 Volley、OkHttp、retrofit等,但是底層邏輯都是一樣的。本節我們來學習 Android 原聲支持的 HTTP 接口,相比那些第三方框架,它的封裝更好,也更適合我們了解底層原理。
對于資源的具體操作類型,由 HTTP 動詞表示。常用的 HTTP 動詞有下面 4 個(括號里是對應的 SQL 命令)。GET(SELECT):從服務器取出資源(一項或多項)POST(CREATE):在服務器新建一個資源PUT(UPDATE):在服務器更新資源(客戶端提供改變后的完整資源)DELETE(DELETE):從服務器刪除資源還有 3 個不常用的 HTTP 動詞。PATCH(UPDATE):在服務器更新(更新)資源(客戶端提供改變的屬性)HEAD:獲取資源的元數OPTIONS:獲取信息,關于資源的哪些屬性是客戶端可以改變的下面是一些例子。GET /classes:列出所有班級POST /classes:新建一個班級(上傳文件)GET /classes/ID:獲取某個指定班級的信息PUT /classes/ID:更新某個指定班級的信息(提供該班級的全部信息)PATCH /classes/ID:更新某個指定班級的信息(提供該班級的部分信息)DELETE /classes/ID:刪除某個班級GET /classes/ID/students:列出某個指定班級的所有學生DELETE /classes/ID/students/ID:刪除某個指定班級的指定學生
正如 HTTP 請求包含四部分一樣,HTTP 的響應同樣包含四個部分。分別是狀態行,消息報頭,空行,以及響應正文。下面這個是我們訪問慕課網后,返回的信息:HTTP/1.1 200 OKServer: nginxContent-Type: text/html; charset=UTF-8Content-Length: 49930Connection: keep-alive<HTML>....第一行為狀態行,同樣的,需要標明 HTTP 協議的版本,然后后面是一個狀態碼。這里的 200 表示請求成功。OK 是用來表明請求的狀態消息,通過消息我們可以對請求的錯誤進行定位。常見的狀態碼如下表所示:狀態碼解釋200 OK請求成功400 Bad Request請求消息有語法錯誤。401 Unauthorized未經授權,必須和WWW-Authenticate報頭域一起使用。403 Forbidden拒絕提供服務404 Not Found請求的資源不存在,或者被移除了500 Internal Server Error服務器端錯誤,通常是服務器端代碼邏輯錯誤造成的503 Server Unavailable服務不可用,有可能需要等一段時間進行恢復Tips:總結一下規律,2 開頭的意味著成功,3 開頭的大部分是重定向,4 開頭是客戶端錯誤,5 開頭的是服務器端的錯誤。第二行的 Server: nginx表明了服務器端采用的服務器名稱。Content-Length: 49930 是消息報頭表明了服務器返回的 HTML 內容的長度。Connection: keep-alive 是空行,空行必須要有,不可省略。最后是響應正文,一般會是一個 HTML 文檔。
上一個小節中,我們簡單的介紹了 HTTP 協議,但是,并沒有針對 HTTP 的請求和響應進行更詳盡的描述。但是,分析請求和響應信息是我們進行爬蟲工作中的重要步驟,因此,有必要詳細的介紹這兩個步驟。我們還是復用之前的訪問慕課網的例子進行 HTTP 協議的解析。關于怎么獲取請求頭和響應頭的信息的內容,我們會在后面講解第一個爬蟲的時候進行講解。使用 get 方法請求慕課網的請求信息如下:GET / HTTP/1.1Host: www.xianlaiwan.cnConnection: keep-aliveCache-Control: max-age=0HTTP 請求主要有四部分組成。分別是請求行,請求頭部,空行和請求數據。
上面我們已經大概了解了什么是 HTTP 協議,簡單來說就是客戶端與服務端用來通信的協議,HTTP 協議中規定和很多 HTTP 方法來讓我們根據不同的需求向服務端發起請求。下面我們通過一個具體的例子,說明如何在 Flask 中使用不同的 HTTP 方法:from flask import Flask, requestapp = Flask(__name__)首先,導入類 flask.Flask 和 flask.request,request 封裝了請求消息,可以獲取請求的各種參數。@app.route('/login', methods = ['GET'])def login(): return '''<form action="/check_login" method="POST"> <p><input type="text" name="name"/></p> <p><input type="password" name="password"/></p> <p><input type="submit" value="submit"/></p></form>'''定義處理路徑 /login 的函數 login,裝飾器 @app.route(’/login’, methods = [‘GET’]) 表示使用 GET 方法處理路徑 /login 的請求。函數 login 返回一段用于登錄的 HTML 表單,表單包括 2 個字段: name 和 password。在第 4 行,指定使用 POST 方法提交表單給服務端的 /check_login 頁面。@app.route('/check_login', methods = ['POST'])def check_login(): name = request.form['name'] password = request.form['password'] if name == 'guest' and password == '123': return 'Login succeed' else: return 'Login failed'定義處理路徑 /check_login 的函數 check_login,裝飾器 @app.route(’/check_login’, methods = [‘POST’]) 表示使用 POST 方法處理路徑 /check_login 的請求。函數 check_login 根據請求的參數 name 和 password 是否正確,返回給用戶相應的信息。在第 3 行,提取參數 name 的值,在第 4 行,提取參數 password 的值。如果 name 是 guest,password 是 123,則返回登錄成功消息,否則返回登錄失敗消息。if __name__ == '__main__': app.run()調用 app.run() 運行程序。用戶在瀏覽器中輸入 http://localhost:5000/login,瀏覽器顯示:用戶輸入正確的 name 和 password 后,瀏覽器跳轉到頁面 http://localhost:5000/check_login,顯示:
Http 底層基于 TCP 協議,分為請求和響應。請求和響應分別有各自的 Header 和 Body 組成。Header 里面通常是本次請求 / 響應的描述信息,比如版本號、長度、UA、Content-Type 等等,而 Body 里面通常就是我們要傳遞的業務數據了,下面分別瀏覽一下請求和響應的內容。
假如我們在瀏覽器輸入慕課網地址:http://www.xianlaiwan.cn/HTTP 的工作流程如下:首先需要傳輸層建立連接,這個是 HTTP 的運作的基礎之一,因為 HTTP 是應用層,它是建立在傳輸層之上的。然后發送一個 HTTP 的請求報文如下:GET / HTTP/1.1Host: www.xianlaiwan.cnConnection: keep-aliveCache-Control: max-age=0...服務端會返回一段報文信息如下:HTTP/1.1 200 OKServer: nginxContent-Type: text/html; charset=UTF-8Content-Length: 49930Connection: keep-alive...瀏覽器渲染服務器返回的信息,并關閉連接或者重用之前的連接。以上就是 HTTP 的基本工作原理。關于請求與響應的具體解釋,我們下一個小節會深入講解。
可以使用 Request 對象中的 header() 方法獲取當前 HTTP 請求的頭信息,代碼如下: public function getInfo(Request $request){ halt($request->header()); }執行結果如下圖所示:
根據 HTTP 標準,常用的 HTTP 請求如下所示:請求方法功能GET請求指定 URL 的頁面,這是最常見的方法HEAD類似于 GET 請求,但返回的響應中沒有具體的內容,用于獲取報頭POST向指定 URL 的頁面提交數據進行處理請求,例如提交表單或者上傳文件PUT從客戶端向服務器傳送數據,取代指定 URL 的頁面DELETE請求服務器刪除指定 URL 的頁面
Http 協議是前后端 API 接口交互的橋梁,不管你是前端開發,移動端開發,后端開發,它都是你工作必不可少的部分。在如今的生產環境中,為了快速實現邏輯業務的開發,往往這部分是被框架封裝得很完整了,初學者就更加容易忽視它,以至于遇到問題無從下手。為什么我資源更新了,界面還是舊的,可能是 Http 緩存了;請求的參數該放路徑還是 Body 中;接口報錯了,返回的狀態碼看不懂;接口文檔如何編寫才是規范的;讓 Http 協議規范自己的軟件開發;雖然 Http 工具封裝得很好用,但我必須搞懂它,要做工具的主人而不是奴隸,必要的時候自己造工具。
本節我們將借助 Socket 實現服務的端口監聽并根據 Http 協議的請求和響應結構,實現一個簡單的 Web 服務器,加深體驗 Web 服務和 Http 協議的原理。
本部分內容將詳細介紹 Nginx 中對 Http請求的 11 個處理階段,分成 3 個小節講解并進行相關實驗操作。
Http 定義了 5大類別的錯誤碼,這些錯誤碼是通用的,其中只有 5XX 是表示后臺服務的錯誤。各個系統的后端服務的用途/業務相差甚遠,為數不多 5XX 遠遠不夠用來表示可能出現的各種情況。于是,后端系統需要根據自己的業務制定業務級別的錯誤碼,而 Http 的錯誤碼,我們稱其為協議級別的錯誤碼。
面試官提問: 請枚舉一些常見的 HTTP 狀態碼,并且說明作用。題目解析:首先我們從性質上分類,HTTP 的響應狀態碼總共有 1XX 到 5XX 五種類型,關于每種狀態碼的定義:狀態碼開頭性質 1XX 服務器收到請求,需要請求者繼續執行操作。2XX 客戶端請求成功,并且服務端成功處理。3XX 重定向,需要進一步的操作以完成請求。4XX 客戶端錯誤,請求包含語法錯誤或者無法完成請求。5XX 服務器錯誤,服務器在處理請求的過程中發生了錯誤。對于 4XX 開頭的錯誤碼,都是因為客戶端自身的原因產生,例如我們輸入 URL:http://www.xianlaiwan.cn/home,因為不存在這個 URL 對應的資源,所以返回 404 Not Found,找不到頁面。對于 5XX 開頭的錯誤碼,都是因為服務器處理過程中遇到異常產生,例如后端開發程序員在處理 HTTP 請求的過程觸發了 Exception,導致響應失敗。在定性之后,面試官大概率還要抽出幾個常見的狀態碼,考察其具體的含義,我們對常見的狀態碼也需要進行總結:狀態碼狀態碼對應英文說明 100Continue 服務器收到了客戶端的請求行和頭部信息,告訴客戶端繼續發送數據部分。200OK 請求成功。301Permanently Moved 資源被永久轉移了,請求將被重定向。302Temporarily Moved 資源被臨時轉移了,請求將被重定向。404Not Found 資源沒找到。500Internal Server Error 服務器內部錯誤。這里需要分區開 301 和 302 錯誤碼(也是常見考點),從字面意思上看,301 和 302 都代表某個 URL 被轉移了,區別在于:(1)301 表示資源被永久轉移了,搜索引擎(例如百度的爬蟲)在爬取網站的時候會抓取新網站的內容并且保留新網站的 URL。(2)302 表示資源被臨時轉移了,也就是臨時重定向,搜索引擎在爬取網站的時候會抓取新的內容,但是保留舊網站作為 URL。