HTTP 請求的工作原理
從開始到結束,當你在瀏覽器中輸入URL時會發生什麼事情
本文描述了瀏覽器如何使用HTTP/1.1協議進行頁面請求
如果你曾經參加過面試,可能會被問到:“當你在Google搜索框中輸入內容並按下Enter鍵時會發生什麼”.
這是一個最常問的問題之一。人們只是想看看你是否能解釋一些相當基本的概念,以及你是否對互聯網的工作原理有任何了解。
在這篇文章中,我將分析當你在瀏覽器的地址欄中輸入URL並按下Enter鍵時會發生什麼。
這是一個非常有趣的主題,我可以在單獨的文章中深入探討其中的許多技術。
這項技術很少更改,並且為人類所建造的最複雜和最廣泛的生態系統之一提供動力。
HTTP協議
首先,我特別提到HTTPS,因為使用HTTPS連接的情況有所不同。
我僅分析URL請求
現代瀏覽器具有知道你在地址欄中輸入的是實際URL還是搜索詞的能力,如果不是有效的URL,它們將使用默認搜索引擎。
我假設你輸入的是實際URL。
當你輸入URL並按下Enter鍵時,瀏覽器首先構建完整的URL。
如果你只輸入了一個域名,例如flaviocopes.com
,瀏覽器默認會在前面添加 HTTP://
,使用預設的HTTP協議。
與macOS / Linux相關的事情
只是提一下。Windows可能會略有不同。
DNS查找階段
瀏覽器開始進行DNS查找以獲取服務器的IP地址。
域名對於我們人類來說很方便,但互聯網根據IP地址對服務器的精確位置進行組織,IP地址是一組類似 222.324.3.1
(IPv4)的數字。
首先,它檢查DNS本地緩存,看看域名最近是否已被解析。
Chrome有一個方便的DNS緩存可視化工具,你可以在chrome://net-internals/#dns查看。
如果在那裡找不到任何內容,瀏覽器將使用DNS解析器,使用gethostbyname
POSIX系統調用檢索主機信息。
gethostbyname
gethostbyname
首先在本地主機文件中查找,該文件在macOS或Linux中位於/etc/hosts
,以查看系統是否在本地提供該信息。
如果這沒有提供有關該域的任何信息,系統將向DNS服務器發送請求。
DNS服務器的地址存儲在系統首選項中。
下面是兩個常用的DNS服務器:
8.8.8.8
:Google公共DNS服務器1.1.1.1
:CloudFlare DNS服務器
大多數人使用由其網絡提供商提供的DNS服務器。
瀏覽器使用UDP協議執行DNS請求。
TCP和UDP是計算機網絡的兩個基礎協議。它們處於相同的概念層級,但TCP是面向連接的協議,而UDP是無連接的協議,更加輕量級,用於以較小開銷發送消息。
如何進行UDP請求不在本教程的範圍內
DNS服務器可能在緩存中有域的IP。如果沒有,它將向樹狀DNS服務器發送請求。這是一個由13台實際服務器(分佈在全球各地)組成的系統,該系統驅動整個互聯網。
DNS服務器不知道地球上每個域名的地址。它只知道頂級DNS解析器的位置。頂級域是域名的擴展名:.com
,.it
,.pizza
等。
一旦根DNS服務器收到請求,它會將請求轉發給頂級域(TLD)DNS服務器。假設你正在尋找flaviocopes.com
,根域DNS服務器會返回.com TLD服務器的IP。
現在我們的DNS解析器將緩存該TLD服務器的IP,所以它不需要再次向根DNS服務器請求。
TLD DNS服務器將具有我們正在查找的域的權威名稱服務器的IP地址。
如何做到的?當你購買一個域名時,域名註冊商會向相應的TDL發送名稱服務器。當你更新名稱服務器(例如,當你更換主機提供商時),你的域名註冊商將自動更新此信息。
這些是主機提供商的DNS服務器。通常有不止1個,以作為備份。
例如:
ns1.dreamhost.com
ns2.dreamhost.com
ns3.dreamhost.com
DNS解析器從第一個開始,並嘗試查詢你正在查找的域名(包括子域名)的IP。
這是IP地址的終極真相來源。
現在我們有了IP地址,可以繼續我們的旅程。
TCP請求握手
有了服務器的IP地址後,瀏覽器現在可以與服務器建立TCP連接。
在開始發送數據之前,TCP連接需要進行一些握手。
建立連接後,我們可以發送請求。
發送請求
請求是一個根據通信協議結構化的純文本文檔。
它由3部分組成:
- 請求行
- 請求標頭
- 請求主體
請求行
請求行在一行上設定以下內容:
- HTTP方法
- 資源位置
- 協議版本
示例:
1 | GET / HTTP/1.1 |
請求標頭
請求標頭是一組field: value
對,用於設定某些值。
其中有2個強制性的字段,其中之一是Host
,另一個是Connection
,而其他所有字段都是可選的:
1 | Host: flaviocopes.com |
Host
指示我們要定位的域名,而Connection
始終設置為close
,除非必須保持連接。
一些最常用的標頭字段有:
Origin
Accept
Accept-Encoding
Cookie
Cache-Control
Dnt
還有許多其他標頭字段。
標頭部分以空行結束。
請求主體
請求主體是可選的,在GET請求中不使用,在POST請求中非常常用,有時在其他動詞中也使用,它可以包含以JSON格式的數據。
由於我們現在正在分析GET請求,因此主體是空的,我們不會再深入研究。
響應
一旦請求被發送,服務器會處理它並發送回響應。
響應以狀態碼和狀態消息開始。如果請求成功並返回200,它將以以下方式開始:
1 | 200 OK |
請求可能返回不同的狀態碼和消息,例如:
1 | 404 Not Found |
然後,響應包含一個HTTP標頭列表和響應主體(由於我們在瀏覽器中進行請求,響應主體將是HTML)。
解析HTML
瀏覽器現在已經收到HTML並開始解析它,並且將為頁面所需的所有資源重複執行完全相同的過程:
- CSS文件
- 圖片
- 網站標誌
- JavaScript文件
- …
瀏覽器如何呈現頁面超出了本範圍,但重要的是理解我描述的過程不僅適用於HTML頁面,而且適用於通過HTTP傳遞的任何項目。
tags: [“http-requests”, “http-protocol”, “networking”, “tcp”, “dns”]