HTTP (HyperText Transfer Protocol, 超文字傳輸協議)是網際網路上應用最為廣泛的一種網路協議,它是基於 TCP 的應用層協議,簡單地說就是客戶端和伺服器進行通訊的一種規則,它的模式非常簡單,就是客戶端發起請求,伺服器響應請求,如下圖所示:
HTTP 最早於 1991 年釋出,是 0.9 版,不過目前該版本已不再用。HTTP 目前在使用的版本主要有:
- HTTP/1.0,於 1996 年 5 月釋出,引入了多種功能,至今仍在使用當中。
- HTTP/1.1,於 1997 年 1 月釋出,持久連線被預設採用,是目前最流行的版本。
- HTTP/2 ,於 2015 年 5 月釋出,引入了伺服器推送等多種功能,是目前最新的版本。
HTTP 請求
HTTP 請求由三部分組成:
- 請求行:包含請求方法、請求地址和 HTTP 協議版本
- 訊息報頭:包含一系列的鍵值對
- 請求正文(可選):注意和訊息報頭之間有一個空行
如圖所示:
下面是一個 HTTP GET 請求的例子:
GET / HTTP/1.1
Host: httpbin.org
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.98 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, sdch, br
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6,zh-TW;q=0.4
Cookie: _ga=GA1.2.475070272.1480418329; _gat=1複製程式碼
上面的第一行就是一個請求行:
GET / HTTP/1.1複製程式碼
其中,GET
是請求方法,表示從伺服器獲取資源;/
是一個請求地址;HTTP/1.1
表明 HTTP 的版本是 1.1。
請求行後面的一系列鍵值對就是訊息報頭:
Host: httpbin.org
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.98 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, sdch, br
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6,zh-TW;q=0.4
Cookie: _ga=GA1.2.475034215.1480418329; _gat=1複製程式碼
其中:
- Host 是請求報頭域,用於指定被請求資源的 Internet 主機和埠號,它通常從 HTTP URL 中提取出來;
- Connection 表示連線狀態,keep-alive 表示該連線是持久連線(persistent connection),即 TCP 連線預設不關閉,可以被多個請求複用,如果客戶端和伺服器發現對方有一段時間沒有活動,就可以主動關閉連線;
- Cache-Control 用於指定快取指令,它的值有 no-cache, no-store, max-age 等,
max-age=秒
表示資源在本地快取多少秒; - User-Agent 用於標識請求者的一些資訊,比如瀏覽器型別和版本,作業系統等;
- Accept 用於指定客戶端希望接受哪些型別的資訊,比如 text/html, image/gif 等;
- Accept-Encoding 用於指定可接受的內容編碼;
- Accept-Language 用於指定可接受的自然語言;
- Cookie 用於維護狀態,可做使用者認證,伺服器檢驗等,它是瀏覽器儲存在使用者電腦上的文字片段;
HTTP 請求方法
HTTP 通過不同的請求方法以多種方式來操作指定的資源,常用的請求方法如下表:
方法 | 描述 |
---|---|
GET | 從伺服器獲取指定(請求地址)的資源的資訊,它通常只用於讀取資料,就像資料庫查詢一樣,不會對資源進行修改。 |
POST | 向指定資源提交資料(比如提交表單,上傳檔案),請求伺服器進行處理。資料被包含在請求正文中,這個請求可能會建立新的資源或更新現有的資源。 |
PUT | 通過指定資源的唯一標識(在伺服器上的具體存放位置),請求伺服器建立或更新資源。 |
DELETE | 請求伺服器刪除指定資源。 |
HEAD | 與 GET 方法類似,從伺服器獲取資源資訊,和 GET 方法不同的是,HEAD 不含有呈現資料,僅僅是 HTTP 頭資訊。HEAD 的好處在於,使用這個方法可以在不必傳輸全部內容的情況下,就可以獲得資源的元資訊(或後設資料)。 |
OPTIONS | 該方法可使伺服器傳回資源所支援的所有 HTTP 請求方法。 |
再議 POST 和 PUT
注意到,POST 和 PUT 都可用於建立或更新資源,然而,它們之間還是有比較大的區別:
- POST 所對應的 URI 並非建立的資源本身,而是資源的接收者,資源本身的存放位置由伺服器決定;而 PUT 所對應的 URI 是要建立或更新的資源本身,它指明瞭具體的存放位置
比如,往某個站點新增一篇文章,如果使用 POST 來建立資源,可類似這樣:
POST /articles HTTP/1.1
{
"author": "ethan",
"title": "hello world",
"content": "hello world"
}複製程式碼
在上面,POST 對應的 URI 是 /articles
,它是資源的接收者,而非資源的標識,如果資源被成功建立,伺服器可以返回 201 Created
狀態以及新建資源的位置,比如:
HTTP/1.1 201 Created
Location: /articles/abcdef123複製程式碼
我們如果知道新建資源的識別符號,可以使用 PUT 來建立資源,比如:
PUT /articles/abcdef234 HTTP/1.1
{
"author": "peter",
"title": "hello world",
"content": "hello world"
}複製程式碼
在上面,PUT 對應的 URI 是 /articles/abcdef234
,它指明瞭資源的存放位置,如果資源被成功建立,伺服器可以返回 201 Created
狀態以及新建資源的位置,比如:
HTTP/1.1 201 Created
Location: /articles/abcdef234複製程式碼
- 使用 PUT 更新某一資源,需要更新資源的全部屬性;而使用 POST,可以更新全部或一部分值
比如使用 PUT 更新地址為 /articles/abcdef234
的文章的標題,我們需要傳送所有值:
PUT /articles/abcdef234 HTTP/1.1
{
"author": "peter",
"title": "hello python",
"content": "hello world"
}複製程式碼
而使用 POST,可以更新某個域的值:
POST /articles/abcdef234 HTTP/1.1
{
"title": "hello python"
}複製程式碼
- POST 是不冪等的,PUT 是冪等的,這是一個很重要的區別
HTTP 方法的冪等性是指一次和多次請求某一個資源應該具有同樣的副作用,注意這裡是副作用,而不是返回結果。
GET 方法用於獲取資源,不會改變資源的狀態,不論呼叫一次還是多次都沒有副作用,因此它是冪等的;DELETE 方法用於刪除資源,有副作用,但呼叫一次或多次都是刪除同個資源,產生的副作用是相同的,因此也是冪等的;POST 是不冪等的,因為兩次相同的 POST 請求會在伺服器建立兩份資源,它們具有不同的 URI;PUT 是冪等的,對同一 URI 進行多次 PUT 的副作用和一次 PUT 是相同的。
HTTP 響應
HTTP 響應與 HTTP 請求相似,由三部分組成:
- 狀態行:包含 HTTP 協議版本、狀態碼和狀態描述,以空格分隔
- 響應頭:即訊息報頭,包含一系列的鍵值對
- 響應正文:返回內容,注意和響應頭之間有一個空行
如圖所示:
下面是一個 HTTP GET 請求的響應結果:
HTTP/1.1 200 OK
Server: nginx
Date: Tue, 29 Nov 2016 13:08:38 GMT
Content-Type: application/json
Content-Length: 203
Connection: close
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
"args": {},
"headers": {
"Host": "httpbin.org",
"User-Agent": "Paw/2.3.1 (Macintosh; OS X/10.11.3) GCDHTTPRequest"
},
"origin": "13.75.42.240",
"url": "https://httpbin.org/get"
}複製程式碼
上面的第一行就是一個狀態行:
HTTP/1.1 200 OK複製程式碼
其中,200
是狀態碼,表示客戶端請求成功,OK
是相應的狀態描述。
狀態碼是一個三位的數字,常見的狀態碼有以下幾類:
- 1XX 訊息 — 請求已被服務接收,繼續處理
- 2XX 成功 — 請求已成功被伺服器接收、理解、並接受
- 200 OK
- 201 Created 已建立
- 202 Accepted 接收
- 203 Non-Authoritative Information 非認證資訊
- 204 No Content 無內容
- 3XX 重定向 — 需要後續操作才能完成這一請求
- 301 Moved Permanently 請求永久重定向
- 302 Moved Temporarily 請求臨時重定向
- 304 Not Modified 檔案未修改,可以直接使用快取的檔案
- 305 Use Proxy 使用代理
- 4XX 請求錯誤 — 請求含有詞法錯誤或者無法被執行
- 400 Bad Request 由於客戶端請求有語法錯誤,不能被伺服器所理解
- 401 Unauthorized 請求未經授權。這個狀態程式碼必須和WWW-Authenticate報頭域一起使用
- 403 Forbidden 伺服器收到請求,但是拒絕提供服務。伺服器通常會在響應正文中給出不提供服務的原因
- 404 Not Found 請求的資源不存在,例如,輸入了錯誤的URL
- 5XX 伺服器錯誤 — 伺服器在處理某個正確請求時發生錯誤
- 500 Internal Server Error 伺服器發生不可預期的錯誤,導致無法完成客戶端的請求
- 503 Service Unavailable 伺服器當前不能夠處理客戶端的請求,在一段時間之後,伺服器可能會恢復正常
- 504 Gateway Time-out 閘道器超時
狀態行後面的一系列鍵值對就是訊息報頭,即響應頭:
Server: nginx
Date: Tue, 29 Nov 2016 13:08:38 GMT
Content-Type: application/json
Content-Length: 203
Connection: close
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true複製程式碼
其中:
- Server 包含了伺服器用來處理請求的軟體資訊,跟請求報頭域 User-Agent 相對應;
- Content-Type 用於指定傳送給接收者(比如瀏覽器)的響應正文的媒體型別,比如 text/html, text/css, image/png, image/jpeg, video/mp4, application/pdf, application/json 等;
- Content-Length 指明本次回應的資料長度;
HTTP 特點
- 客戶端/伺服器模式
- 簡單快速:客戶端向伺服器請求服務時,通過傳送請求方法、請求地址和資料體(可選)即可
- 靈活:允許傳輸任意型別的資料物件,通過 Content-Type 標識
- 無狀態:對事物處理沒記憶能力
小結
- HTTP 是在網路上傳輸 HTML 的協議,用於瀏覽器和伺服器的通訊,預設使用 80 埠。
- URL 地址用於定位資源,HTTP 中的 GET, POST, PUT, DELETE 用於操作資源,比如查詢,增加,更新等。
- GET, PUT, DELETE 是冪等的,POST 是不冪等的。
- POST VS PUT
- 使用 PUT 建立資源需要提供資源的唯一標識(具體存放位置),POST 不需要,POST 的資料存放位置由伺服器自己決定
- 使用 PUT 更新某一資源,需要更新資源的全部屬性;而使用 POST,可以更新全部或一部分值
- POST 是不冪等的,PUT 是冪等的,這是一個很重要的區別
- GET 可提交的資料量受到 URL 長度的限制,HTTP 協議規範沒有對 URL 長度進行限制,這個限制是特定的瀏覽器及伺服器對它的限制。
- 理論上講,POST 是沒有大小限制的,HTTP 協議規範也沒有進行大小限制,出於安全考慮,伺服器軟體在實現時會做一定限制。
本文由 funhacks 發表於個人部落格,採用 Creative Commons BY-NC-ND 4.0(自由轉載-保持署名-非商用-禁止演繹)協議釋出。
非商業轉載請註明作者及出處。商業轉載請聯絡作者本人。
本文標題為: HTTP 協議簡介
本文連結為: funhacks.net/2017/03/01/…