從Chrome源碼看HTTP
本篇解讀基於Chromium 66。HTTP協議起很大作用的是http頭,它主要是由一個個鍵值對組成的,例如Content-Type: text/html表示發送的數據是html格式,而Content-Encoding: gzip指定了內容是使用gzip壓縮的,Transfer-Encoding: chunked又表示它使用分塊傳輸編碼,等等。
從Chrome發的請求複製一個原始的請求報文頭如下所示,如訪問http://payment-admin.com/list將會發送以下請求報文:
"GET /list HTTP/1.1
Host: payment-admin.com
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3345.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
If-None-Match: W/"68104920-260-"2018-02-13T14:16:35.000Z""
If-Modified-Since: Tue, 13 Feb 2018 14:16:35 GMT
"
這個是按照http報文格式拼接的字元串,如下圖所示:
對於每個請求,Chrome都會自動設置UA欄位:
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3345.0 Safari/537.36
Chrome的UA欄位是這麼拼的:
Mozilla/5.0 ([os_info]) AppleWebKit/[webkit_major_version].[webkit_minor_version] (KHTML, like Gecko) [chrome_version] Safari/[webkit_major_version].[webkit_minor_version]
如下源碼所示:
並且我們看到源碼的注釋還說明了為什麼UA要帶上Safari——為了以最大限度地與Safari兼容的方式展示產品名稱。
當前請求收到了以下響應報文頭:
"HTTP/1.1 200 OK Server: nginx/1.8.0 Date: Fri, 16 Feb 2018 03:31:51 GMT Content-Type: text/html; charset=UTF-8 Transfer-Encoding: chunked Connection: keep-alive last-modified: Tue, 13 Feb 2018 14:16:35 GMT etag: W/"68104920-260-"2018-02-13T14:16:35.000Z"" cache-control: max-age=10