未完全完成,先發出來再說。
HTTP(Hypertext Transfer Protocol,超文本傳輸協議)是應用層的無狀態的請求和響應協議。它使得基於網絡的超文本信息系統彼此可以靈活地進行交互。它包含了可拓展的語義(extensible semantics)和自描述的有效報文載荷(self-descriptive message payloads)。
- 應用層:OSI 七層模型的頂層;
定義請求頭; - 自描述的:指報文本身描述了處理這個報文的方式,例如 HTML 最開始的
<!DOCTYPE
; - 有效報文載荷:真正需要的數據,HTML 內容或者 JSON 串;
- 注:從表示上看,像解釋型語言(與編譯型語言相對)。其內容可以被所有編程語言處理,因此不受限於特定編程語言和特定平臺。基於不同編程語言的系統可以通過 HTTP 進行交互。
歷史
最早對 HTTP/1.1 做出說明的 RFC 文檔是 1997 年發佈的 RFC2068。在 1999 年發佈的 RFC2616 對 RFC2068 做了更新。
當前關於 HTTP/1.1 最新的文檔是 2014 年發佈的 RFC7230、RFC7231、RFC7232、RFC7233、RFC7234、RFC7235 ,它們將 RFC2616 的內容拆分開來並做詳細的解釋與更新。
在 RFC INDEX 頁面可以看到它們之間的關係:
2068 Hypertext Transfer Protocol -- HTTP/1.1 R. Fielding, J. Gettys, J. Mogul, H. Frystyk, T. Berners-Lee [ January 1997 ] (TXT, HTML) (Obsoleted-By RFC2616) (Status: PROPOSED STANDARD) (Stream: IETF, Area: app, WG: http) (DOI: 10.17487/RFC2068)
2616 Hypertext Transfer Protocol -- HTTP/1.1 R. Fielding, J. Gettys, J. Mogul, H. Frystyk, L. Masinter, P. Leach, T. Berners-Lee [ June 1999 ] (TXT, PS, PDF, HTML) (Obsoletes RFC2068) (Obsoleted-By RFC7230, RFC7231, RFC7232, RFC7233, RFC7234, RFC7235) (Updated-By RFC2817, RFC5785, RFC6266, RFC6585) (Status: DRAFT STANDARD) (Stream: IETF, Area: app, WG: http) (DOI: 10.17487/RFC2616)
7230 Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing R. Fielding, J. Reschke [ June 2014 ] (TXT, HTML) (Obsoletes RFC2145, RFC2616) (Updates RFC2817, RFC2818) (Updated-By RFC8615) (Status: PROPOSED STANDARD) (Stream: IETF, Area: app, WG: httpbis) (DOI: 10.17487/RFC7230)
具體的內容見:
- https://tools.ietf.org/html/rfc2068:過時的
- https://tools.ietf.org/html/rfc2616:過時的
- https://tools.ietf.org/html/rfc7230
- https://tools.ietf.org/html/rfc7231
- https://tools.ietf.org/html/rfc7232
- https://tools.ietf.org/html/rfc7233
- https://tools.ietf.org/html/rfc7234
- https://tools.ietf.org/html/rfc7235
內容
本文會對 RFC7230-7235 的內容做個大概的說明(翻譯),並且在必要的時候做詳細說明(翻譯)。
- RFC7230:語法和路由
語法:描述了一個 HTTP 請求或者響應長什麼樣。即第一行寫什麼怎麼寫、第二行寫什麼怎麼寫...
路由:資源標識(URI)如何確定?通過什麼方式獲取到想要的內容?是直接從本地緩存獲取?還是通過代理(Proxy)獲取?還是直接請求? - RFC7231:語義和內容(最需要關注的內容,RESTful-like)
各種請求方法(GET、POST、DELETE 等等)和請求頭(Expect、Accept-Language、User-Agent 等等)表達了什麼意圖?
響應體的狀態(200 OK、201 Created、403 Forbidden 等等)和響應頭(Location、Retry-After、Allow 等等)表達什麼意思? - RFC7232:條件請求
響應體告知客戶端某些數據條件(Last-Modified、ETag 等等),客戶端可以在下次請求的時候帶上這些信息(If-Modified-Since、If-Match 等等)。在符合條件或者不符合條件的情況下,服務端應該如何處理; - RFC7233:範圍請求
由於各種因素而只得到部分響應的時候,發起範圍請求以獲取剩下的內容,避免從頭請求而浪費資源; - RFC7234:緩存
通過減少請求避免網絡資源的浪費; - RFC7235:認證
用戶認證。Basic Auth、Token 等等。
RFC7230:語法和路由
客戶端和服務端
客戶端發起連接請求給服務端,服務端接收來自客戶端的請求,並建立連接。
用戶代理(User Agent)
用於表示各種客戶端程序,例如瀏覽器、爬蟲、命令行工具、手機應用等等。
源服務器(Origin Server)
用於表示對客戶端請求的資源生成一個權威性的響應的程序。
HTTP 通過 URI 確定目標資源和資源間的關係。
請求的語法
例子:
GET /hello.txt HTTP/1.1
User-Agent: curl/7.16.3 libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3
Host: www.example.com
Accept-Language: en, mi
- 第 1 行(請求行)包含三個信息:請求方法、URI、HTTP 版本
- 第 2-4 行是請求頭(Headers)
- 請求頭以一個空行作爲結束標誌
- 在空行後面是真正想要發送的報文——有效載荷體(payload body),如果沒有就放空。
響應的語法
例子:
HTTP/1.1 200 OK
Date: Mon, 27 Jul 2009 12:28:53 GMT
Server: Apache
Last-Modified: Wed, 22 Jul 2009 19:15:56 GMT
ETag: "34aa387-d-1568eb00"
Accept-Ranges: bytes
Content-Length: 51
Vary: Accept-Encoding
Content-Type: text/plain
Hello World! My payload includes a trailing CRLF.
- 第 1 行(狀態行)包含三個信息:HTTP 版本、狀態碼、原因
- 第 2-9 行是響應頭(Header)
- 響應頭以一個空行作爲結束標誌
- 在空行後面是客戶端想要的報文——有效載荷體(payload body),如果沒有就放空。
中轉(Intermediaries)
從 User Agent 到 Origin Server,中間可以經過各種中轉。中轉通常有三種:代理(Proxy)、網關(Gateway)和隧道(Tunnel)。
> > > >
UA =========== A =========== B =========== C =========== O
< < < <
- 入站(Inbound)和出站(Outbound)
入站表示朝向源服務器,出站表示朝向用戶代理。 - 代理(Proxy)
一種由客戶端選擇的報文轉發代理(message-forwarding agent)。按照一定規則讓請求通過同一個中轉。 - 網關(Gateway)
又稱爲反向代理(Reverse Proxy)。對於出站連接來說,網關就像是源服務器。經常被用於攔截不被信任的服務、提高服務器性能、負載均衡等等。 - 隧道(Tunnel)
通常被用於建立一條虛擬的連接。通過這條連接的報文不會發生變化。 - 透明代理(Transparent Proxy)
不是由客戶端選擇的代理。例如在路由器上建立代理,電腦的瀏覽器感知不到這個代理。
無狀態
HTTP 是無狀態的協議。這意味着每個請求都能夠被獨立地理解。
但是由於代理會複用連接或者動態負載均衡的存在,服務端不應該認爲來自同一條連接的請求來自於同一個用戶代理(User Agent)。
緩存
緩存用於存放先前的響應報文,它還作爲子系統管理着緩存的抽取和刪除。
使用緩存的目的是減少未來發起與先前等價的請求時所帶來的響應耗時和網絡帶寬的消耗。
> >
UA =========== A =========== B - - - - - - C - - - - - - O
< <
在 B 緩存了先前的響應報文後,UA 發出的請求就不必再經過 C 和 O 了。
一個響應是否會被緩存,由多個因素決定。在 RFC7234 裏有詳細的說明。
協議版本
格式是:<major>.<minor>
但從 HTTP/2 開始,僅保留 major 。例如 HTTP/3。
RFC7231:語義和內容
請求方法
請求方法表明客戶端發起請求的目的,以及客戶端所預期的成功結果。
Representation (表徵):
the way that someone or something is shown or described.
人或物被展示或者描述的方式。
+---------+-------------------------------------------------+-------+
| Method | Description | Sec. |
+---------+-------------------------------------------------+-------+
| GET | 傳輸目標資源的一種表徵 | 4.3.1 |
| HEAD | 和 GET 相同,但只傳輸狀態和頭部 | 4.3.2 |
| POST | 執行請求有效載荷中特定於資源的處理 | 4.3.3 |
| PUT | 用請求有效載荷替換資源的所有表徵 | 4.3.4 |
| DELETE | 刪除目標資源的所有表徵 | 4.3.5 |
| CONNECT | 建立一條與目標資源指定的服務器之間的隧道 | 4.3.6 |
| OPTIONS | 描述與目標資源相關的選項 | 4.3.7 |
| TRACE | 執行一個沿着客戶端到目標資源路徑的消息回送測試 | 4.3.8 |
+---------+-------------------------------------------------+-------+
這些方法可以按照不同屬性分類:
- 安全(safe)和非安全(unsafe)
安全的方法不會造成目標資源的狀態改變。方法包括 GET/HEAD/OPTIONS/TRACE。 - 冪等(idempotent)
同一個請求執行一次或者多次,對服務端資源的影響是一致的。
冪等的方法包括所有的安全方法,還有 PUT/DELETE。例如多次 DELETE 同一個資源,對於服務端來說,最終的結果都是該資源不存在。執行一次或者執行多次都一樣。
冪等容易被誤解爲對客戶端來說的冪等,導致難以理解爲什麼 GET 也是冪等的:畢竟每次 GET 返回的結果都可能不一樣。因此要注意站在服務端資源的角度來看。 - 可緩存(cacheable)
響應結果可存儲起來供後續使用。方法包括 GET/HEAD/POST。
大多數的緩存實現都只實現 GET/HEAD,但 RFC 7231 多定義了一個 POST。
這部分內容在 RFC 7234 有詳細介紹。
方法定義
GET
HEAD
POST
POST 根據結果選擇合適的狀態碼:
- 201 Created
一個或多個資源創建成功後,返回該狀態碼。同時要在頭部加上 Location,指向創建的主要資源。 - 206 Partial Content
- 303 See Other
如果 POST 的處理結果與一個已存在資源的某一種表徵一致,那麼服務端在處理完 POST 後,可以用 303 重定向到已存在的資源。
這是爲了共享緩存,但如果客戶端代理之前沒有緩存該已存在資源的表徵,則會因爲 303 而額外地發起一次請求。 - 304 Not Modified
- 416 Range Not Satisfiable
PUT
服務端應校驗服務端對目標資源的配置,例如內容的類型。
PUT 根據結果選擇合適的狀態碼:
- 200 OK
目標資源已存在,此次更新成功 - 201 Created
目標資源先前不存在,此次執行創建了該資源。 - 204 No Content
目標資源已存在,此次更新成功 - 400 Bad Request
客戶端請求頭包含 Content-Range。部分更新應使用 PATCH。 - 409 Conflict
- 415 Unsupported Media Type
服務端對資源配置的 Content-Type 與客戶端配置的不一致。例如服務端限定只能是text/html
,而客戶端在 HTTP 頭部配置的是image/jpeg
。
這只是一種處理方式,其他兩種處理方式爲:- 服務端將客戶端傳輸的類型轉換爲服務端配置的類型,然後存儲
- 服務端變更配置,將 Content-Type 配置爲客戶端設置的類型
DELETE
DELETE 表達的是源服務器 URL 映射的一種刪除操作,而不是一種刪除先前關聯信息的期望。和 rm 命令類似,只刪除映射,並沒有將數據清除。
一個資源如果有一種或者多種表徵,源服務器可以選擇是否清除數據,也可以選擇是否回收數據的存儲空間。
當使用 PUT 創建資源和 POST 創建資源後,可以用 DELETE 來撤銷(undo)這些操作。
DELETE 根據結果選擇合適的狀態碼:
- 200 OK
操作成功,且響應體包含了描述結果的信息 - 202 Accepted
操作很可能成功,但還未執行或者還未執行完成。 - 204 No Content
操作成功,且不需要返回更多的信息給客戶端
由於刪除操作是冪等的,因此多次刪除同一個資源讓源服務器對於該資源處於同一個狀態。
OPTIONS
OPTIONS 用於獲取目標資源所支持的選項。OPTIONS 沒有對目標資源做出修改。
OPTIONS 支持兩種資源類型:
*
用於類似 ping 或者空操作。- 非
*
用於獲取可用的適用於目標資源的選項。
服務端在生成響應的時候,應該發送服務端實現的適用於目標資源的任何可選特性的頭部。例如 Allow。此外還包括潛在的沒有定義在 RFC 7221 的擴展。
OPTIONS 響應允許包含響應體,用於描述通信選項。如果不包含響應體,其 Content-Length 必須設置爲 0。
OPTIONS 請求允許包含請求體。此時請求頭必須包含 Content-Type 頭部描述請求體的媒體類型。
CONNECT
CONNECT 用於建立從參與者到源服務器之間的通道。
TRACE
TRACE 請求應用層級別的迴環
請求頭字段
起控制作用的請求頭
+-------------------+
| Header Field Name |
+-------------------+
| Cache-Control |
| Expect |
| Host |
| Max-Forwards |
| Pragma |
| Range |
| TE |
+-------------------+
- Max-Forwards
只用於 TRACE 和 HEAD 請求方法。它的值是一個十進制整數,用於表示代理剩餘可轉發次數。
起條件作用的請求頭(RFC 7232)
+---------------------+
| Header Field Name |
+---------------------+
| If-Match |
| If-None-Match |
| If-Modified-Since |
| If-Unmodified-Since |
| If-Range |
+---------------------+
服務端響應一個資源的時候,可以包含響應專用的 ETag 和 Modified-Since 兩個響應頭,表示資源的版本。
客戶端可以在後續請求時,將 ETag 的值放在 If-Match 或者 If-None-Match 上,將 Modified-Since 的值放在 If-Modified-Since 或者 If-Unmodified-Since 上。
-
If-Match
If-Match 的值可以加雙引號,值可以有多個,多個值用逗號隔開。值還可以是*
,表示匹配任意 ETag,但如果一個都沒有的時候,爲 false。匹配方式使用強匹配。- 當客戶端要更新一個資源,使用了 If-Match 頭,它要求當前服務端該資源的 ETag 應該是剛纔 GET 資源時所獲得的 ETag。避免覆蓋掉其他請求對該資源的更新,或者避免更新請求的響應丟失時重試。
- 當 If-Match 用於安全的請求方法(如 GET)時,如果服務端資源的 ETag 與之不匹配,則終止該請求。
-
If-None-Match
- 使用弱匹配。
- 如果客戶端要初始化一個資源,使用了 If-None-Match 頭,它要求當前資源的 ETag 不是剛纔獲得的 ETag 才能更新。例如將 If-None-Match 設置爲
*
,避免多個初始化請求時後者覆蓋前者。 - 當 If-None-Match 爲 false 時:
- 如果使用 GET 或者 HEAD,返回 304 Not Modified
- 如果使用其他請求方法,則返回 412 Precondition Failed
-
If-Modified-Since
如果請求頭還包含 If-None-Match,則忽略 If-Modified-Since
如果服務端發現資源的最後一次修改時間早於或者等於 If-Modified-Since 指定的時間,則不執行操作而是返回 304 Not Modified -
If-Unmodified-Since
如果請求頭還包含 If-Match,則忽略 If-Unmodified-Since
避免覆蓋其他的修改
如果服務端發現資源的最後一次修改時間晚於 If-Modified-Since 指定的時間,則不執行操作,返回 412 Precondition Failed 或者 2xx。返回 2xx 的場景是請求的操作給資源帶來的最終狀態與當前狀態一致。
如果客戶端使用 GET 或者 HEAD 時,想要通過請求頭來嘗試命中緩存,則應該使用以下兩個請求頭:
- If-None-Match 表示 “如果不匹配該 ETag,則返回最新的數據”。如果響應的狀態碼是 304 Not Modified ,則表示客戶端傳送的 ETag 與服務端的一致。
- If-Modified-Since 表示 “這個時間之後資源如果已被修改,則返回最新的數據”。如果響應的狀態碼是 304 Not Modified ,則表示資源在客戶端指定的時間之後沒有再被修改了。
起內容協商作用的請求頭
主要協商服務端應該返回的數據類型。
+-------------------+
| Header Field Name |
+-------------------+
| Accept |
| Accept-Charset |
| Accept-Encoding |
| Accept-Language |
+-------------------+
- Accept
媒體類型,例如 text/plain。
對應響應頭爲: Content-Type - Accept-Charset
字符集 unicode - Accept-Encoding
字符編碼,例如 gzip。
對應響應頭爲: Content-Encoding - Accept-Language
語言
協商頭的值可以多個,用逗號隔開,表示服務端可以根據情況選擇。每種選項都有一個比重(0 ~ 1),用分號與選項隔開,放在分號之後。可以省略比重,此時會被解釋爲 1。
例如:
Accept: text/plain; q=0.5, text/html, text/x-dvi; q=0.8, text/x-c
表示更希望獲取 text/html 或者 text/x-c 這兩種媒體類型。如果服務器不支持這兩種類型,則返回 text/x-dvi 這種類型。如果也不支持 text/x-dvi,則返回 text/plain 這種類型。如果都不支持,則返回 406 Not Acceptable 。
響應狀態碼
1xx 信息
-
100 Continue
當客戶端的 Expect 頭部包含 100-continue 的時候,服務端返回該狀態碼錶示知道客戶端要發送大量的數據,並且初始數據已被接收,服務端當前不打算拒絕該請求,客戶端可以繼續發送請求。RFC 7231 對 Expect 的值只定義了 100-continue 這一種。如果客戶端傳送了其他值,服務端可能返回 417 Expectation Failed。
-
101 Switching Protocols
客戶端頭部包含 Upgrade 時,服務端返回該狀態碼錶示願意切換協議。
2xx 成功
- 200 OK
- 201 Created
成功創建資源後,在響應頭 Location 中返回資源的位置。
在實踐中,會碰到一個問題:客戶端並不總是關心該資源的位置,而是關注查看該資源內容的前端地址。不能將該地址放在響應體,因爲 201 要求響應體必須爲空。應該把這個鏈接信息放到響應頭 Link 裏面。 - 202 Accepted
服務端接受客戶端的請求,但請求未處理完。服務端返回當前處理的狀態,以及指向該處理的狀態監測器。客戶端可使用該監測器獲取執行狀態。 - 203 Non-Authoritative Information
由代理返回。表示請求成功,服務端返回了 200,但由於響應有效載荷被轉換代理修改,因此返回該狀態碼。 - 204 No Content
- 205 Reset Content
讓客戶端將導致剛剛請求被髮送的那部分頁面(例如表單)重置爲它的初始狀態。
3xx 重定向
表示用戶代理需要再做其他動作來滿足剛纔的請求。比如 Location 字段指定了一個 URI,用戶代理可能自動重定向到該 URI。
重定向有四種類型:
- 資源可能在一個不同的 URI 上可以用。屬於這種類型的狀態碼包括:
- 301 (Moved Permanently)
- 302 (Found)
- 307 (Temporary Redirect)
- 請求的資源有多種表徵,客戶端可以選擇最合適的表徵。屬於這種類型的狀態碼包括:
- 300 (Multiple Choices)
- 重定向到一個不同的資源,該資源代表了對請求的間接響應。屬於這種類型的狀態碼包括:
- 303 (See Other)
- 重定向到一個已緩存的結果。屬於這種類型的狀態碼包括:
- 304 (Not Modified)
以下是各個狀態碼的補充說明:
- 300 Multiple Choices
請求的資源存在,但是有多種表徵。由於客戶端沒有明確表示需要哪種表徵,服務端無法替客戶端決定。服務端將這些不同表徵的 URI 放在頭部 Link 中。
服務端可在 Location 指定服務端傾向的其中一種表徵,供客戶端自動重定向。 - 301 Moved Permanently
目標資源被分配了新的 永久 的 URI,後續請求應該使用新的 URI。服務端將新的 URI 放在 Location 中,客戶端可以根據這個字段的值自動重定向。
由於歷史原因,用戶代理一旦收到該狀態碼,後續請求可能將 POST 轉爲 GET。如果不能接受這樣的轉換,則應該使用 307 Temporary Redirect。 - 302 Found
目標資源 暫時 存放在不同的 URI,後續請求應該使用原先的 URI。服務端將新的 URI 放在 Location 中,客戶端可以根據這個字段的值自動重定向。
由於歷史原因,用戶代理一旦收到該狀態碼,後續請求可能將 POST 轉爲 GET。如果不能接受這樣的轉換,則應該使用 307 Temporary Redirect。 - 303 See Other
服務端讓客戶端重定向到一個不同的資源,該資源的 URI 放在 Location 中,目的是爲原始請求提供一個間接的響應。這種重定向可能持續多次,並且用戶代理應該將最終的結果作爲原始請求的響應。
例如 POST 創建資源後,可以使用這個狀態碼將客戶端重定向至新資源的地址。 - 304 Not Modified(RFC 7232)
當 GET 或者 HEAD 請求附帶 Last-Modified 或 ETag 時,如果滿足條件,則返回該狀態碼。表示客戶端數據的版本已是最新,服務端不再返回這些數據。
響應頭應包含以下頭部的任何一個:Cache-Control, Content-Location, Date, ETag, Expires 和 Vary 。 - 305 Use Proxy(已廢棄)
- 306 Unused(已廢棄)
- 307 Temporary Redirect
目標資源 暫時 存放在不同的 URI,後續請求應該使用原先的 URI。服務端將新的 URI 放在 Location 中,客戶端可以根據這個字段的值自動重定向。
用戶代理在自動重定向的時候 禁止改變 請求方法。 - 308 Permanent Redirect(RFC 7238)
目標資源被分配了新的 永久 的 URI,後續請求應該使用新的 URI。服務端將新的 URI 放在 Location 中,客戶端可以根據這個字段的值自動重定向。
用戶代理在自動重定向的時候 禁止改變 請求方法。
需要特別注意的是:
狀態碼 | 暫時/永久 | 可能改變請求方法 | RFC |
---|---|---|---|
301 | 永久 | 是 | 7231 |
302 | 暫時 | 是 | 7231 |
307 | 暫時 | 否 | 7231 |
308 | 永久 | 否 | 7238 |
4xx 客戶端錯誤
憑據(credential):登錄過的證明。如 Cookie,Token。
- 400 Bad Request
請求的句法有問題(例如請求的第一行不按照標準來)、欺騙性的請求路由、不合法的請求內容等。當其他 4xx 無法表達錯誤類型的時候,也使用該狀態碼。 - 401 Unauthorized(RFC 7235)
不包含有效的憑據。服務端的響應頭必須包含 WWW-Authenticate,告知具體原因。無效的憑據:空憑據、過期憑據。 - 402 Payment Required
僅作爲保留狀態碼,以便未來對此狀態碼做具體定義。 - 403 Forbidden
資源存在,但客戶端沒有權限訪問。分爲帶有效憑據和無效憑據的情況。但最終都要求客戶端提供一個有效且具有權限的憑據。 - 404 Not Found
服務端當前沒有找到請求的資源。404 並不意味着資源在未來不會出現。如果服務端通過一些信息知道該資源永遠不會再出現,則應返回 410 Gone。
未必找不到資源才返回 404。在實踐中,如果服務端不想暴露 “資源存在” 這一信息給客戶端,則可以返回該狀態碼。 - 405 Method Not Allowed
目標資源不支持該請求方法。例如某個資源不支持 DELETE,而客戶端對該資源發起 DELETE 請求。 - 406 Not Acceptable
客戶端請求頭包含 Accept、Accept-Charset、Accept-Encoding、Accept-Language 時,服務端發現資源無法滿足客戶端的要求,且不想返回一個默認的資源表徵。
服務端應該在響應的有效載荷中列出可用的選擇。 - 407 Proxy Authentication Required(RFC 7235)
類似於 401,但 407 用於客戶端和代理之間。用於表示如果要使用代理,必須提供有效憑據。代理的響應頭必須包含 Proxy-Authenticate,告知具體原因。 - 408 Request Timeout
服務端未能在特定時間內接收一個完整的請求,並且要關閉該連接。 - 409 Conflict
請求與目標資源當前的狀態產生衝突。
常出現在對版本化的資源做 PUT 時,資源已被其他請求變更,當前請求不是基於資源最新版本變更的。服務端可以在響應的有效載荷裏面包含幫助客戶端合併兩個版本的信息。
這個狀態碼在一些地方被用於 POST 請求的響應,用於表示要創建的資源已存在。 - 410 Gone
與 404 相似,但 410 表示資源很可能永遠都不存在。 - 411 Length Required
客戶端請求頭不包含 Content-Length - 412 Precondition Failed(RFC 7232)
請求頭中一個或者多個測試條件不滿足。客戶端想要在目標資源處於某種狀態的時候才更新該資源,而如果客戶端所預期的狀態和該資源當前的狀態不一致,則返回該狀態碼。 - 413 Payload Too Large
請求體(有效載荷)的大小超過了服務端設置的限制。如果這種限制是臨時的,則服務端響應頭應包含 Retry-After 表示客戶端可以過一段時間再嘗試。 - 414 URI Too Long
URI 太長。可能是由於重定向導致 POST 轉爲 GET,也可能是客戶端惡意攻擊,還可能是客戶端不小心傳了過多的數據。 - 415 Unsupported Media Type
客戶端請求頭 Content-Type 或者 Content-Encoding 指定的值,或者服務端根據請求體的內容來識別,發現其類型不被目標資源所支持。 - 417 Expectation Failed
跟客戶端請求頭 Expect 對應(只定義了 100-continue 一種)。如果客戶端傳送了服務端不支持的 Expect 類型,則報錯。 - 422 Unprocessable Entity(RFC 4918)
導致 400 的條件都不滿足的情況下,服務端仍然無法處理該請求。
可以用於業務校驗不通過的場景。 - 426 Upgrade Required
客戶端的請求由於 HTTP 版本過低被服務端拒絕執行,如果客戶端願意升級 HTTP 版本,服務端纔會執行。
響應頭必須包含 Upgrade。例如 Upgrade: HTTP/3.0
需要特別注意的是:
- 401 和 403 的區別(登錄、權限)
- 404 和 410 的區別(是否永久不存在)
- 408 和 504 的區別(服務端接收客戶端超時、代理接收服務端超時)
- 409 的場景(資源支持版本)
5xx 服務端錯誤
- 500 Internal Server Error
客戶端請求沒問題,但服務端碰到了錯誤,導致無法執行完請求。 - 501 Not Implemented
客戶端使用的請求方法服務端沒有實現,即對任意資源都不能使用該請求方法。 - 502 Bad Gateway
網關或者代理服務器收到了一份來自上游服務器的非法響應。 - 503 Service Unavailable
服務端因爲暫時性的負載過高或者臨時維護導致服務無法使用。
如果負載過高,服務端不一定使用該狀態碼,而是直接拒絕連接。 - 504 Gateway Timeout
網關或者代理服務器未能在指定時間內收到上游服務器的響應。 - 505 HTTP Version Not Supported
服務端不支持或者拒絕支持客戶端使用的 HTTP 主版本。